mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-20 07:27:19 -05:00
Monstat2 loading and a bunch of lint issues (#491)
* MonStat2 loader * Fix a bunch of lint issues in d2datadict
This commit is contained in:
parent
b29e7c8fdd
commit
aae565d528
@ -39,10 +39,10 @@ type AutoMapRecord struct {
|
||||
// whatever you like..."
|
||||
// The values seem functional but naming conventions
|
||||
// vary between LevelNames.
|
||||
//Type1 string
|
||||
//Type2 string
|
||||
//Type3 string
|
||||
//Type4 string // Note: I commented these out for now because they supposedly aren't useful see the LoadAutoMaps function.
|
||||
// Type1 string
|
||||
// Type2 string
|
||||
// Type3 string
|
||||
// Type4 string // Note: I commented these out for now because they supposedly aren't useful see the LoadAutoMaps function.
|
||||
|
||||
// Frames determine the frame of the MaxiMap(s).dc6 that
|
||||
// will be applied to the specified tiles. The frames
|
||||
@ -58,6 +58,7 @@ type AutoMapRecord struct {
|
||||
}
|
||||
|
||||
// AutoMaps contains all data in AutoMap.txt.
|
||||
//nolint:gochecknoglobals // Current design is to have these global
|
||||
var AutoMaps []*AutoMapRecord
|
||||
|
||||
// LoadAutoMaps populates AutoMaps with the data from AutoMap.txt.
|
||||
@ -71,9 +72,9 @@ func LoadAutoMaps(file []byte) {
|
||||
|
||||
// Construct records
|
||||
AutoMaps = make([]*AutoMapRecord, len(d.Data))
|
||||
|
||||
for idx := range d.Data {
|
||||
// Row 2603 is a separator with all empty field values
|
||||
if idx == 2603 {
|
||||
if d.GetString("LevelName", idx) == "Expansion" {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -88,7 +89,9 @@ func LoadAutoMaps(file []byte) {
|
||||
//Type1: d.GetString("Type1", idx),
|
||||
//Type2: d.GetString("Type2", idx),
|
||||
//Type3: d.GetString("Type3", idx),
|
||||
//Type4: d.GetString("Type4", idx), // Note: I commented these out for now because they supposedly aren't useful see the AutoMapRecord struct.
|
||||
//Type4: d.GetString("Type4", idx),
|
||||
// Note: I commented these out for now because they supposedly
|
||||
// aren't useful see the AutoMapRecord struct.
|
||||
}
|
||||
|
||||
AutoMaps[idx].Frames = make([]int, len(frameFields))
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
)
|
||||
|
||||
// Charecter stats
|
||||
type CharStatsRecord struct {
|
||||
Class d2enum.Hero
|
||||
|
||||
@ -59,8 +60,8 @@ var CharStats map[d2enum.Hero]*CharStatsRecord
|
||||
var charStringMap map[string]d2enum.Hero
|
||||
var weaponTokenMap map[string]d2enum.WeaponClass
|
||||
|
||||
//nolint:funlen // Makes no sense to split
|
||||
func LoadCharStats(file []byte) {
|
||||
|
||||
charStringMap = map[string]d2enum.Hero{
|
||||
"Amazon": d2enum.HeroAmazon,
|
||||
"Barbarian": d2enum.HeroBarbarian,
|
||||
@ -186,5 +187,6 @@ func LoadCharStats(file []byte) {
|
||||
}
|
||||
CharStats[record.Class] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d CharStats records", len(CharStats))
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ type CubeRecipeItemProperty struct {
|
||||
// string or an integer.
|
||||
//
|
||||
// See: https://d2mods.info/forum/kb/viewarticle?a=345
|
||||
//"the parameter passed on to the associated property, this is used to pass skill IDs,
|
||||
// "the parameter passed on to the associated property, this is used to pass skill IDs,
|
||||
// state IDs, monster IDs, montype IDs and the like on to the properties that require
|
||||
// them, these fields support calculations."
|
||||
Param int // for properties that use parameters
|
||||
@ -153,7 +153,6 @@ var inputFields = []string{"input 1", "input 2", "input 3", "input 4", "input 5"
|
||||
// LoadCubeRecipes populates CubeRecipes with
|
||||
// the data from CubeMain.txt.
|
||||
func LoadCubeRecipes(file []byte) {
|
||||
|
||||
// Load data
|
||||
d := d2common.LoadDataDictionary(string(file))
|
||||
|
||||
@ -188,7 +187,6 @@ func LoadCubeRecipes(file []byte) {
|
||||
// Create outputs - output "", b, c
|
||||
CubeRecipes[idx].Outputs = make([]CubeRecipeResult, 3)
|
||||
for o, outLabel := range outputLabels {
|
||||
|
||||
CubeRecipes[idx].Outputs[o] = CubeRecipeResult{
|
||||
Item: newCubeRecipeItem(
|
||||
d.GetString(outputFields[o], idx)),
|
||||
@ -201,7 +199,6 @@ func LoadCubeRecipes(file []byte) {
|
||||
// Create properties - mod 1-5
|
||||
properties := make([]CubeRecipeItemProperty, 5)
|
||||
for p, prop := range propLabels {
|
||||
|
||||
properties[p] = CubeRecipeItemProperty{
|
||||
Code: d.GetString(outLabel+prop, idx),
|
||||
Chance: d.GetNumber(outLabel+prop+" chance", idx),
|
||||
@ -213,7 +210,6 @@ func LoadCubeRecipes(file []byte) {
|
||||
|
||||
CubeRecipes[idx].Outputs[o].Properties = properties
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d CubeMainRecord records", len(CubeRecipes))
|
||||
@ -237,21 +233,26 @@ func newCubeRecipeItem(f string) CubeRecipeItem {
|
||||
// Find the qty parameter if it was provided,
|
||||
// convert to int and assign to item.Count
|
||||
for idx, arg := range args {
|
||||
if strings.HasPrefix(arg, "qty") {
|
||||
count, err := strconv.Atoi(strings.Split(arg, "=")[1])
|
||||
if err != nil {
|
||||
log.Fatal("Error parsing item count:", err)
|
||||
}
|
||||
item.Count = count
|
||||
|
||||
// Remove the qty parameter
|
||||
if idx != len(args)-1 {
|
||||
args[idx] = args[len(args)-1]
|
||||
}
|
||||
args = args[:len(args)-1]
|
||||
|
||||
break
|
||||
if !strings.HasPrefix(arg, "qty") {
|
||||
continue
|
||||
}
|
||||
|
||||
count, err := strconv.Atoi(strings.Split(arg, "=")[1])
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Error parsing item count:", err)
|
||||
}
|
||||
|
||||
item.Count = count
|
||||
|
||||
// Remove the qty parameter
|
||||
if idx != len(args)-1 {
|
||||
args[idx] = args[len(args)-1]
|
||||
}
|
||||
|
||||
args = args[:len(args)-1]
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
// No other arguments were provided
|
||||
@ -272,10 +273,12 @@ func newCubeRecipeItem(f string) CubeRecipeItem {
|
||||
func classFieldToEnum(f string) []d2enum.Hero {
|
||||
split := splitFieldValue(f)
|
||||
enums := make([]d2enum.Hero, len(split))
|
||||
|
||||
for idx, class := range split {
|
||||
if class == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch class {
|
||||
case "bar":
|
||||
enums[idx] = d2enum.HeroBarbarian
|
||||
@ -295,6 +298,7 @@ func classFieldToEnum(f string) []d2enum.Hero {
|
||||
log.Fatalf("Unknown hero token: '%s'", class)
|
||||
}
|
||||
}
|
||||
|
||||
return enums
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,11 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
// DifficultyLevels contain the difficulty records for each difficulty
|
||||
//nolint:gochecknoglobals // Current design is to have these global
|
||||
var DifficultyLevels map[string]*DifficultyLevelRecord
|
||||
|
||||
// DifficultyLevelRecord contain the parameters that change for different difficultios
|
||||
type DifficultyLevelRecord struct {
|
||||
// Difficulty name. it is hardcoded and you cannot add new ones unless you do
|
||||
// some Code Edits
|
||||
@ -30,7 +33,7 @@ type DifficultyLevelRecord struct {
|
||||
// txt file...
|
||||
|
||||
// Not used. Pre 1.07 it was the percentage of magic, rare, set and unique
|
||||
// exceptional items dropped on this difficuly.
|
||||
// exceptional items dropped on this difficulty.
|
||||
DropChanceMagic int // UberCodeOddsGood
|
||||
DropChanceRare int // UberCodeOddsGood
|
||||
DropChanceSet int // UberCodeOddsGood
|
||||
@ -89,6 +92,7 @@ type DifficultyLevelRecord struct {
|
||||
|
||||
}
|
||||
|
||||
// LoadDifficultyLevels is a loader for difficultylevels.txt
|
||||
func LoadDifficultyLevels(file []byte) {
|
||||
dict := d2common.LoadDataDictionary(string(file))
|
||||
numRows := len(dict.Data)
|
||||
@ -119,5 +123,4 @@ func LoadDifficultyLevels(file []byte) {
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d DifficultyLevel records", len(DifficultyLevels))
|
||||
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ func LoadExperienceBreakpoints(file []byte) {
|
||||
d2enum.HeroPaladin: d.GetNumber("Paladin", idx),
|
||||
d2enum.HeroSorceress: d.GetNumber("Sorceress", idx),
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@ -108,5 +109,6 @@ func LoadExperienceBreakpoints(file []byte) {
|
||||
|
||||
ExperienceBreakpoints[record.Level] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d ExperienceBreakpoint records", len(ExperienceBreakpoints))
|
||||
}
|
||||
|
@ -52,7 +52,9 @@ type GemsRecord struct {
|
||||
|
||||
func LoadGems(file []byte) {
|
||||
d := d2common.LoadDataDictionary(string(file))
|
||||
|
||||
var Gems []*GemsRecord
|
||||
|
||||
for idx := range d.Data {
|
||||
if d.GetString("name", idx) != "Expansion" {
|
||||
/*
|
||||
@ -105,5 +107,6 @@ func LoadGems(file []byte) {
|
||||
Gems = append(Gems, gem)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d Gems records", len(Gems))
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
type HirelingRecord struct {
|
||||
Hireling string
|
||||
SubType string
|
||||
Id int
|
||||
ID int
|
||||
Class int
|
||||
Act int
|
||||
Difficulty int
|
||||
@ -84,11 +84,12 @@ type HirelingRecord struct {
|
||||
func LoadHireling(file []byte) {
|
||||
d := d2common.LoadDataDictionary(string(file))
|
||||
var Hirelings []*HirelingRecord
|
||||
|
||||
for idx := range d.Data {
|
||||
hireling := &HirelingRecord{
|
||||
Hireling: d.GetString("Hireling", idx),
|
||||
SubType: d.GetString("SubType", idx),
|
||||
Id: d.GetNumber("Id", idx),
|
||||
ID: d.GetNumber("Id", idx),
|
||||
Class: d.GetNumber("Class", idx),
|
||||
Act: d.GetNumber("Act", idx),
|
||||
Difficulty: d.GetNumber("Difficulty", idx),
|
||||
@ -161,5 +162,6 @@ func LoadHireling(file []byte) {
|
||||
}
|
||||
Hirelings = append(Hirelings, hireling)
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d Hireling records", len(Hirelings))
|
||||
}
|
||||
|
@ -16,26 +16,28 @@ var MagicSuffixRecords []*ItemAffixCommonRecord
|
||||
|
||||
var AffixMagicGroups []*ItemAffixCommonGroup
|
||||
|
||||
var superType d2enum.ItemAffixSuperType
|
||||
var subType d2enum.ItemAffixSubType
|
||||
|
||||
// LoadMagicPrefix loads MagicPrefix.txt
|
||||
func LoadMagicPrefix(file []byte) {
|
||||
superType = d2enum.ItemAffixPrefix
|
||||
subType = d2enum.ItemAffixMagic
|
||||
superType := d2enum.ItemAffixPrefix
|
||||
|
||||
subType := d2enum.ItemAffixMagic
|
||||
|
||||
MagicPrefixDictionary, MagicPrefixRecords = loadDictionary(file, superType, subType)
|
||||
}
|
||||
|
||||
// LoadMagicSuffix loads MagicSuffix.txt
|
||||
func LoadMagicSuffix(file []byte) {
|
||||
superType = d2enum.ItemAffixSuffix
|
||||
subType = d2enum.ItemAffixMagic
|
||||
superType := d2enum.ItemAffixSuffix
|
||||
|
||||
subType := d2enum.ItemAffixMagic
|
||||
|
||||
MagicSuffixDictionary, MagicSuffixRecords = loadDictionary(file, superType, subType)
|
||||
}
|
||||
|
||||
func getAffixString(t1 d2enum.ItemAffixSuperType, t2 d2enum.ItemAffixSubType) string {
|
||||
var name string = ""
|
||||
|
||||
switch t2 {
|
||||
case d2enum.ItemAffixMagic:
|
||||
if t2 == d2enum.ItemAffixMagic {
|
||||
name = "Magic"
|
||||
}
|
||||
|
||||
@ -47,7 +49,6 @@ func getAffixString(t1 d2enum.ItemAffixSuperType, t2 d2enum.ItemAffixSubType) st
|
||||
}
|
||||
|
||||
return name
|
||||
|
||||
}
|
||||
|
||||
func loadDictionary(
|
||||
@ -59,6 +60,7 @@ func loadDictionary(
|
||||
records := createItemAffixRecords(dict, superType, subType)
|
||||
name := getAffixString(superType, subType)
|
||||
log.Printf("Loaded %d %s records", len(dict.Data), name)
|
||||
|
||||
return dict, records
|
||||
}
|
||||
|
||||
@ -111,8 +113,8 @@ func createItemAffixRecords(
|
||||
subType d2enum.ItemAffixSubType,
|
||||
) []*ItemAffixCommonRecord {
|
||||
records := make([]*ItemAffixCommonRecord, 0)
|
||||
for index := range d.Data {
|
||||
|
||||
for index := range d.Data {
|
||||
affix := &ItemAffixCommonRecord{
|
||||
Name: d.GetString("Name", index),
|
||||
Version: d.GetNumber("version", index),
|
||||
@ -179,6 +181,7 @@ func createItemAffixRecords(
|
||||
|
||||
records = append(records, affix)
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
||||
|
||||
@ -193,14 +196,17 @@ func (g *ItemAffixCommonGroup) AddMember(a *ItemAffixCommonRecord) {
|
||||
if g.Members == nil {
|
||||
g.Members = make(map[string]*ItemAffixCommonRecord)
|
||||
}
|
||||
|
||||
g.Members[a.Name] = a
|
||||
}
|
||||
|
||||
func (g *ItemAffixCommonGroup) GetTotalFrequency() int {
|
||||
total := 0
|
||||
|
||||
for _, affix := range g.Members {
|
||||
total += affix.Frequency
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
@ -249,6 +255,8 @@ func (a *ItemAffixCommonRecord) ProbabilityToSpawn(qlvl int) float64 {
|
||||
if (qlvl > a.MaxLevel) || (qlvl < a.Level) {
|
||||
return 0.0
|
||||
}
|
||||
p := (float64)(a.Frequency) / (float64)(a.Group.GetTotalFrequency())
|
||||
|
||||
p := float64(a.Frequency) / float64(a.Group.GetTotalFrequency())
|
||||
|
||||
return p
|
||||
}
|
||||
|
@ -181,30 +181,35 @@ type ItemVendorParams struct {
|
||||
MagicLevel uint8
|
||||
}
|
||||
|
||||
// Loading Functions
|
||||
var CommonItems map[string]*ItemCommonRecord
|
||||
|
||||
func LoadCommonItems(file []byte, source d2enum.InventoryItemType) *map[string]*ItemCommonRecord {
|
||||
if CommonItems == nil {
|
||||
CommonItems = make(map[string]*ItemCommonRecord)
|
||||
}
|
||||
|
||||
items := make(map[string]*ItemCommonRecord)
|
||||
data := strings.Split(string(file), "\r\n")
|
||||
mapping := MapHeaders(data[0])
|
||||
|
||||
for lineno, line := range data {
|
||||
if lineno == 0 {
|
||||
continue
|
||||
}
|
||||
if len(line) == 0 {
|
||||
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
rec := createCommonItemRecord(line, &mapping, source)
|
||||
items[rec.Code] = &rec
|
||||
CommonItems[rec.Code] = &rec
|
||||
}
|
||||
|
||||
return &items
|
||||
}
|
||||
|
||||
//nolint:funlen // Makes no sens to split
|
||||
func createCommonItemRecord(line string, mapping *map[string]int, source d2enum.InventoryItemType) ItemCommonRecord {
|
||||
r := strings.Split(line, "\t")
|
||||
result := ItemCommonRecord{
|
||||
@ -363,6 +368,7 @@ func createCommonItemRecord(line string, mapping *map[string]int, source d2enum.
|
||||
|
||||
Multibuy: MapLoadBool(&r, mapping, "multibuy"),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -398,6 +404,7 @@ func createItemVendorParams(r *[]string, mapping *map[string]int) map[string]*It
|
||||
}
|
||||
result[name] = &wvp
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -407,5 +414,6 @@ func createItemUsageStats(r *[]string, mapping *map[string]int) [3]ItemUsageStat
|
||||
result[i].Stat = MapLoadString(r, mapping, "stat"+strconv.Itoa(i))
|
||||
result[i].Calc = d2common.CalcString(MapLoadString(r, mapping, "calc"+strconv.Itoa(i)))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -115,10 +115,10 @@ const (
|
||||
// just adds the stat to the unit directly
|
||||
OpDefault = OperatorType(iota)
|
||||
|
||||
// adds opstat.base * statvalue / 100 to the opstat.
|
||||
// Op1 adds opstat.base * statvalue / 100 to the opstat.
|
||||
Op1
|
||||
|
||||
// adds (statvalue * basevalue) / (2 ^ param) to the opstat
|
||||
// Op2 adds (statvalue * basevalue) / (2 ^ param) to the opstat
|
||||
// this does not work properly with any stat other then level because of the
|
||||
// way this is updated, it is only refreshed when you re-equip the item,
|
||||
// your character is saved or you level up, similar to passive skills, just
|
||||
@ -127,56 +127,56 @@ const (
|
||||
// description every frame, while the values remain unchanged serverside.
|
||||
Op2
|
||||
|
||||
// this is a percentage based version of op #2
|
||||
// Op3 is a percentage based version of op #2
|
||||
// look at op #2 for information about the formula behind it, just
|
||||
// remember the stat is increased by a percentage rather then by adding
|
||||
// an integer.
|
||||
Op3
|
||||
|
||||
// this works the same way op #2 works, however the stat bonus is
|
||||
// Op4 works the same way op #2 works, however the stat bonus is
|
||||
// added to the item and not to the player (so that +defense per level
|
||||
// properly adds the defense to the armor and not to the character
|
||||
// directly!)
|
||||
Op4
|
||||
|
||||
// this works like op #4 but is percentage based, it is used for percentage
|
||||
// Op5 works like op #4 but is percentage based, it is used for percentage
|
||||
// based increase of stats that are found on the item itself, and not stats
|
||||
// that are found on the character.
|
||||
Op5
|
||||
|
||||
// like for op #7, however this adds a plain bonus to the stat, and just
|
||||
// Op6 works like for op #7, however this adds a plain bonus to the stat, and just
|
||||
// like #7 it also doesn't work so I won't bother to explain the arithmetic
|
||||
// behind it either.
|
||||
Op6
|
||||
|
||||
// this is used to increase a stat based on the current daytime of the game
|
||||
// Op7 is used to increase a stat based on the current daytime of the game
|
||||
// world by a percentage, there is no need to explain the arithmetics
|
||||
// behind it because frankly enough it just doesn't work serverside, it
|
||||
// only updates clientside so this op is essentially useless.
|
||||
Op7
|
||||
|
||||
// hardcoded to work only with maxmana, this will apply the proper amount
|
||||
// Op8 hardcoded to work only with maxmana, this will apply the proper amount
|
||||
// of mana to your character based on CharStats.txt for the amount of energy
|
||||
// the stat added (doesn't work for non characters)
|
||||
Op8
|
||||
|
||||
// hardcoded to work only with maxhp and maxstamina, this will apply the
|
||||
// Op9 hardcoded to work only with maxhp and maxstamina, this will apply the
|
||||
// proper amount of maxhp and maxstamina to your character based on
|
||||
// CharStats.txt for the amount of vitality the stat added (doesn't work
|
||||
// for non characters)
|
||||
Op9
|
||||
|
||||
// doesn't do anything, this has no switch case in the op function.
|
||||
// Op10 doesn't do anything, this has no switch case in the op function.
|
||||
Op10
|
||||
|
||||
// adds opstat.base * statvalue / 100 similar to 1 and 13, the code just
|
||||
// Op11 adds opstat.base * statvalue / 100 similar to 1 and 13, the code just
|
||||
// does a few more checks
|
||||
Op11
|
||||
|
||||
// doesn't do anything, this has no switch case in the op function.
|
||||
// Op12 doesn't do anything, this has no switch case in the op function.
|
||||
Op12
|
||||
|
||||
// adds opstat.base * statvalue / 100 to the value of opstat, this is
|
||||
// Op13 adds opstat.base * statvalue / 100 to the value of opstat, this is
|
||||
// useable only on items it will not apply the bonus to other unit types
|
||||
// (this is why it is used for +% durability, +% level requirement,
|
||||
// +% damage, +% defense ).
|
||||
@ -241,6 +241,7 @@ stuff
|
||||
|
||||
var ItemStatCosts map[string]*ItemStatCostRecord
|
||||
|
||||
// LoadItemStatCosts loads ItemStatCostRecord's from text
|
||||
func LoadItemStatCosts(file []byte) {
|
||||
d := d2common.LoadDataDictionary(string(file))
|
||||
numRecords := len(d.Data)
|
||||
@ -317,5 +318,6 @@ func LoadItemStatCosts(file []byte) {
|
||||
|
||||
ItemStatCosts[record.Name] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d ItemStatCost records", len(ItemStatCosts))
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ type LevelMazeDetailsRecord struct {
|
||||
// ID from Levels.txt
|
||||
// NOTE: Cave 1 is the Den of Evil, its associated treasure level is quest
|
||||
// only.
|
||||
LevelId int // Level
|
||||
LevelID int // Level
|
||||
|
||||
// the minimum number of .ds1 map sections that will make up the maze in
|
||||
// Normal, Nightmare and Hell difficulties.
|
||||
@ -36,21 +36,24 @@ type LevelMazeDetailsRecord struct {
|
||||
|
||||
var LevelMazeDetails map[int]*LevelMazeDetailsRecord
|
||||
|
||||
// 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)
|
||||
|
||||
for idx := range dict.Data {
|
||||
record := &LevelMazeDetailsRecord{
|
||||
Name: dict.GetString("Name", idx),
|
||||
LevelId: dict.GetNumber("Level", 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),
|
||||
}
|
||||
LevelMazeDetails[record.LevelId] = record
|
||||
LevelMazeDetails[record.LevelID] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d LevelMazeDetails records", len(LevelMazeDetails))
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
|
||||
type LevelPresetRecord struct {
|
||||
Name string
|
||||
DefinitionId int
|
||||
LevelId int
|
||||
DefinitionID int
|
||||
LevelID int
|
||||
Populate bool
|
||||
Logicals bool
|
||||
Outdoors bool
|
||||
@ -39,8 +39,8 @@ func createLevelPresetRecord(props []string) LevelPresetRecord {
|
||||
}
|
||||
result := LevelPresetRecord{
|
||||
Name: props[inc()],
|
||||
DefinitionId: d2common.StringToInt(props[inc()]),
|
||||
LevelId: d2common.StringToInt(props[inc()]),
|
||||
DefinitionID: d2common.StringToInt(props[inc()]),
|
||||
LevelID: d2common.StringToInt(props[inc()]),
|
||||
Populate: d2common.StringToUint8(props[inc()]) == 1,
|
||||
Logicals: d2common.StringToUint8(props[inc()]) == 1,
|
||||
Outdoors: d2common.StringToUint8(props[inc()]) == 1,
|
||||
@ -66,31 +66,39 @@ func createLevelPresetRecord(props []string) LevelPresetRecord {
|
||||
Beta: d2common.StringToUint8(props[inc()]) == 1,
|
||||
Expansion: d2common.StringToUint8(props[inc()]) == 1,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var LevelPresets map[int]LevelPresetRecord
|
||||
|
||||
// LoadLevelPresets loads level presets from text file
|
||||
func LoadLevelPresets(file []byte) {
|
||||
LevelPresets = make(map[int]LevelPresetRecord)
|
||||
data := strings.Split(string(file), "\r\n")[1:]
|
||||
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
props := strings.Split(line, "\t")
|
||||
|
||||
if props[1] == "" {
|
||||
continue // any line without a definition id is skipped (e.g. the "Expansion" line)
|
||||
}
|
||||
|
||||
rec := createLevelPresetRecord(props)
|
||||
LevelPresets[rec.DefinitionId] = rec
|
||||
LevelPresets[rec.DefinitionID] = rec
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d level presets", len(LevelPresets))
|
||||
}
|
||||
|
||||
// LevelPreset looks up a LevelPresetRecord by ID
|
||||
func LevelPreset(id int) LevelPresetRecord {
|
||||
for i := 0; i < len(LevelPresets); i++ {
|
||||
if LevelPresets[i].DefinitionId == id {
|
||||
if LevelPresets[i].DefinitionID == id {
|
||||
return LevelPresets[i]
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ type LevelSubstitutionRecord struct {
|
||||
// groups. If you count each row of a group starting from 0, then you'll
|
||||
// obtain what is written in Levels.txt, columns 'SubTheme', 'SubWaypoint'
|
||||
// and 'SubShrine'. (added by Paul Siramy)
|
||||
Id int // Type
|
||||
ID int // Type
|
||||
|
||||
// What .ds1 is being used.
|
||||
File string // File
|
||||
@ -69,10 +69,9 @@ func LoadLevelSubstitutions(file []byte) {
|
||||
LevelSubstitutions = make(map[int]*LevelSubstitutionRecord, numRecords)
|
||||
|
||||
for idx := range dict.Data {
|
||||
|
||||
record := &LevelSubstitutionRecord{
|
||||
Name: dict.GetString("Name", idx),
|
||||
Id: dict.GetNumber("Type", idx),
|
||||
ID: dict.GetNumber("Type", idx),
|
||||
File: dict.GetString("File", idx),
|
||||
IsExpansion: dict.GetNumber("Expansion", idx) > 0,
|
||||
BorderType: dict.GetNumber("BordType", idx),
|
||||
@ -95,7 +94,8 @@ func LoadLevelSubstitutions(file []byte) {
|
||||
GridMax4: dict.GetNumber("Max4", idx),
|
||||
}
|
||||
|
||||
LevelSubstitutions[record.Id] = record
|
||||
LevelSubstitutions[record.ID] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d LevelSubstitution records", len(LevelSubstitutions))
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
type LevelTypeRecord struct {
|
||||
Name string
|
||||
Id int
|
||||
ID int
|
||||
Files [32]string
|
||||
Beta bool
|
||||
Act int
|
||||
@ -21,29 +21,35 @@ var LevelTypes []LevelTypeRecord
|
||||
func LoadLevelTypes(file []byte) {
|
||||
data := strings.Split(string(file), "\r\n")[1:]
|
||||
LevelTypes = make([]LevelTypeRecord, len(data))
|
||||
|
||||
for i, j := 0, 0; i < len(data); i, j = i+1, j+1 {
|
||||
idx := -1
|
||||
inc := func() int {
|
||||
idx++
|
||||
return idx
|
||||
}
|
||||
if len(data[i]) == 0 {
|
||||
|
||||
if data[i] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.Split(data[i], "\t")
|
||||
|
||||
if parts[0] == "Expansion" {
|
||||
j--
|
||||
continue
|
||||
}
|
||||
|
||||
LevelTypes[j].Name = parts[inc()]
|
||||
LevelTypes[j].Id = d2common.StringToInt(parts[inc()])
|
||||
LevelTypes[j].ID = d2common.StringToInt(parts[inc()])
|
||||
|
||||
for fileIdx := range LevelTypes[i].Files {
|
||||
LevelTypes[j].Files[fileIdx] = parts[inc()]
|
||||
if LevelTypes[j].Files[fileIdx] == "0" {
|
||||
LevelTypes[j].Files[fileIdx] = ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LevelTypes[j].Beta = parts[inc()] != "1"
|
||||
LevelTypes[j].Act = d2common.StringToInt(parts[inc()])
|
||||
LevelTypes[j].Expansion = parts[inc()] != "1"
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type LevelWarpRecord struct {
|
||||
Id int32
|
||||
ID int32
|
||||
SelectX int32
|
||||
SelectY int32
|
||||
SelectDX int32
|
||||
@ -21,16 +21,20 @@ type LevelWarpRecord struct {
|
||||
Direction string
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
// LevelWarps loaded from txt records
|
||||
var LevelWarps map[int]*LevelWarpRecord
|
||||
|
||||
// LoadLevelWarps loads LevelWarpRecord's from text file data
|
||||
func LoadLevelWarps(levelWarpData []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].ID = int32(id)
|
||||
LevelWarps[id].SelectX = streamReader.GetInt32()
|
||||
LevelWarps[id].SelectY = streamReader.GetInt32()
|
||||
LevelWarps[id].SelectDX = streamReader.GetInt32()
|
||||
@ -44,5 +48,6 @@ func LoadLevelWarps(levelWarpData []byte) {
|
||||
LevelWarps[id].Direction = string(streamReader.GetByte())
|
||||
streamReader.SkipBytes(3)
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d level warps", len(LevelWarps))
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ type LevelDetailsRecord struct {
|
||||
// additional layers.
|
||||
AutomapIndex int // Layer
|
||||
|
||||
// sizeX - SizeY in each difficuly. If this is a preset area this sets the
|
||||
// sizeX - SizeY in each difficulty. If this is a preset area this sets the
|
||||
// X size for the area. Othervise use the same value here that are used in
|
||||
// lvlprest.txt to set the size for the .ds1 file.
|
||||
SizeXNormal int // SizeX
|
||||
@ -102,7 +102,7 @@ type LevelDetailsRecord struct {
|
||||
// cycles, because they always use the light values specified in Intensity,
|
||||
// Red, Green, Blue. this field also controls whenever sounds will echo if
|
||||
// you're running the game with a sound card capable of it and have
|
||||
// enviroment sound effects set to true.
|
||||
// environment sound effects set to true.
|
||||
IsInside bool // IsInside
|
||||
|
||||
// Setting for Level Generation: You have 3 possibilities here:
|
||||
@ -141,28 +141,28 @@ type LevelDetailsRecord struct {
|
||||
// linked with, but the actuall number of Vis ( 0 - 7 ) is determined by
|
||||
// your actual map (the .ds1 fle).
|
||||
// Example: Normally Cave levels are only using vis 0-3 and wilderness areas 4-7 .
|
||||
LevelLinkId0 int // Vis0
|
||||
LevelLinkId1 int // Vis1
|
||||
LevelLinkId2 int // Vis2
|
||||
LevelLinkId3 int // Vis3
|
||||
LevelLinkId4 int // Vis4
|
||||
LevelLinkId5 int // Vis5
|
||||
LevelLinkId6 int // Vis6
|
||||
LevelLinkId7 int // Vis7
|
||||
LevelLinkID0 int // Vis0
|
||||
LevelLinkID1 int // Vis1
|
||||
LevelLinkID2 int // Vis2
|
||||
LevelLinkID3 int // Vis3
|
||||
LevelLinkID4 int // Vis4
|
||||
LevelLinkID5 int // Vis5
|
||||
LevelLinkID6 int // Vis6
|
||||
LevelLinkID7 int // Vis7
|
||||
|
||||
// This controls the visual graphics then you move the mouse pointer over
|
||||
// an entrance. To show the graphics you use an ID from lvlwarp.txt and the
|
||||
// behavior on the graphics is controlled by lvlwarp.txt. Your Warps must
|
||||
// match your Vis.
|
||||
// Example: If your level uses Vis 3,5,7 then you must also use Warp 3,5,7 .
|
||||
WarpGraphicsId0 int // Warp0
|
||||
WarpGraphicsId1 int // Warp1
|
||||
WarpGraphicsId2 int // Warp2
|
||||
WarpGraphicsId3 int // Warp3
|
||||
WarpGraphicsId4 int // Warp4
|
||||
WarpGraphicsId5 int // Warp5
|
||||
WarpGraphicsId6 int // Warp6
|
||||
WarpGraphicsId7 int // Warp7
|
||||
WarpGraphicsID0 int // Warp0
|
||||
WarpGraphicsID1 int // Warp1
|
||||
WarpGraphicsID2 int // Warp2
|
||||
WarpGraphicsID3 int // Warp3
|
||||
WarpGraphicsID4 int // Warp4
|
||||
WarpGraphicsID5 int // Warp5
|
||||
WarpGraphicsID6 int // Warp6
|
||||
WarpGraphicsID7 int // Warp7
|
||||
|
||||
// These settings handle the light intensity as well as its RGB components
|
||||
LightIntensity int // Intensity
|
||||
@ -195,7 +195,7 @@ type LevelDetailsRecord struct {
|
||||
|
||||
// What quest is this level related to. This is the quest id (as example the
|
||||
// first quest Den of Evil are set to 1, since its the first quest).
|
||||
QuestId int // Quest
|
||||
QuestID int // Quest
|
||||
|
||||
// This sets the minimum distance from a VisX or WarpX location that a
|
||||
// monster, object or tile can be spawned at. (also applies to waypoints and
|
||||
@ -247,40 +247,40 @@ type LevelDetailsRecord struct {
|
||||
// Hell. They tell the game which monster ID taken from MonStats.txt.
|
||||
// NOTE: you need to manually add from mon11 to mon25 and from nmon11 to
|
||||
// nmon25 !
|
||||
MonsterId1Normal string // mon1
|
||||
MonsterId2Normal string // mon2
|
||||
MonsterId3Normal string // mon3
|
||||
MonsterId4Normal string // mon4
|
||||
MonsterId5Normal string // mon5
|
||||
MonsterId6Normal string // mon6
|
||||
MonsterId7Normal string // mon7
|
||||
MonsterId8Normal string // mon8
|
||||
MonsterId9Normal string // mon9
|
||||
MonsterId10Normal string // mon10
|
||||
MonsterID1Normal string // mon1
|
||||
MonsterID2Normal string // mon2
|
||||
MonsterID3Normal string // mon3
|
||||
MonsterID4Normal string // mon4
|
||||
MonsterID5Normal string // mon5
|
||||
MonsterID6Normal string // mon6
|
||||
MonsterID7Normal string // mon7
|
||||
MonsterID8Normal string // mon8
|
||||
MonsterID9Normal string // mon9
|
||||
MonsterID10Normal string // mon10
|
||||
|
||||
MonsterId1Nightmare string // nmon1
|
||||
MonsterId2Nightmare string // nmon2
|
||||
MonsterId3Nightmare string // nmon3
|
||||
MonsterId4Nightmare string // nmon4
|
||||
MonsterId5Nightmare string // nmon5
|
||||
MonsterId6Nightmare string // nmon6
|
||||
MonsterId7Nightmare string // nmon7
|
||||
MonsterId8Nightmare string // nmon8
|
||||
MonsterId9Nightmare string // nmon9
|
||||
MonsterId10Nightmare string // nmon10
|
||||
MonsterID1Nightmare string // nmon1
|
||||
MonsterID2Nightmare string // nmon2
|
||||
MonsterID3Nightmare string // nmon3
|
||||
MonsterID4Nightmare string // nmon4
|
||||
MonsterID5Nightmare string // nmon5
|
||||
MonsterID6Nightmare string // nmon6
|
||||
MonsterID7Nightmare string // nmon7
|
||||
MonsterID8Nightmare string // nmon8
|
||||
MonsterID9Nightmare string // nmon9
|
||||
MonsterID10Nightmare string // nmon10
|
||||
|
||||
// Gravestench - adding additional fields for Hell, original txt combined
|
||||
// the nighmare and hell ID's stringo the same field
|
||||
MonsterId1Hell string // nmon1
|
||||
MonsterId2Hell string // nmon2
|
||||
MonsterId3Hell string // nmon3
|
||||
MonsterId4Hell string // nmon4
|
||||
MonsterId5Hell string // nmon5
|
||||
MonsterId6Hell string // nmon6
|
||||
MonsterId7Hell string // nmon7
|
||||
MonsterId8Hell string // nmon8
|
||||
MonsterId9Hell string // nmon9
|
||||
MonsterId10Hell string // nmon10
|
||||
MonsterID1Hell string // nmon1
|
||||
MonsterID2Hell string // nmon2
|
||||
MonsterID3Hell string // nmon3
|
||||
MonsterID4Hell string // nmon4
|
||||
MonsterID5Hell string // nmon5
|
||||
MonsterID6Hell string // nmon6
|
||||
MonsterID7Hell string // nmon7
|
||||
MonsterID8Hell string // nmon8
|
||||
MonsterID9Hell string // nmon9
|
||||
MonsterID10Hell string // nmon10
|
||||
|
||||
// Give preference to monsters set to ranged=1 in MonStats.txt on Nightmare
|
||||
// and Hell difficulties when picking something to spawn.
|
||||
@ -293,24 +293,24 @@ type LevelDetailsRecord struct {
|
||||
// NOTE: you can allow umon1-25 to also work in Nightmare and Hell by
|
||||
// following this simple ASM edit
|
||||
// (https://d2mods.info/forum/viewtopic.php?f=8&t=53969&p=425179&hilit=umon#p425179)
|
||||
MonsterUniqueId1 string // umon1
|
||||
MonsterUniqueId2 string // umon2
|
||||
MonsterUniqueId3 string // umon3
|
||||
MonsterUniqueId4 string // umon4
|
||||
MonsterUniqueId5 string // umon5
|
||||
MonsterUniqueId6 string // umon6
|
||||
MonsterUniqueId7 string // umon7
|
||||
MonsterUniqueId8 string // umon8
|
||||
MonsterUniqueId9 string // umon9
|
||||
MonsterUniqueId10 string // umon10
|
||||
MonsterUniqueID1 string // umon1
|
||||
MonsterUniqueID2 string // umon2
|
||||
MonsterUniqueID3 string // umon3
|
||||
MonsterUniqueID4 string // umon4
|
||||
MonsterUniqueID5 string // umon5
|
||||
MonsterUniqueID6 string // umon6
|
||||
MonsterUniqueID7 string // umon7
|
||||
MonsterUniqueID8 string // umon8
|
||||
MonsterUniqueID9 string // umon9
|
||||
MonsterUniqueID10 string // umon10
|
||||
|
||||
// Critter Species 1-4. Uses the Id from monstats2.txt and only monsters
|
||||
// with critter column set to 1 can spawn here. critter column is also found
|
||||
// in monstats2.txt. Critters are in reality only present clientside.
|
||||
MonsterCritterId1 string // cmon1
|
||||
MonsterCritterId2 string // cmon2
|
||||
MonsterCritterId3 string // cmon3
|
||||
MonsterCritterId4 string // cmon4
|
||||
MonsterCritterID1 string // cmon1
|
||||
MonsterCritterID2 string // cmon2
|
||||
MonsterCritterID3 string // cmon3
|
||||
MonsterCritterID4 string // cmon4
|
||||
|
||||
// Controls the chance for a critter to spawn.
|
||||
MonsterCritter1SpawnChance int // cpct1
|
||||
@ -330,13 +330,13 @@ type LevelDetailsRecord struct {
|
||||
// Themes
|
||||
|
||||
// Referes to a entry in SoundEnviron.txt (for the Levels Music)
|
||||
SoundEnvironmentId int // SoundEnv
|
||||
SoundEnvironmentID int // SoundEnv
|
||||
|
||||
// 255 means no Waipoint for this level, while others state the Waypoint' ID
|
||||
// for the level
|
||||
// NOTE: you can switch waypoint destinations between areas this way, not
|
||||
// between acts however so don't even bother to try.
|
||||
WaypointId int // Waypoint
|
||||
WaypointID int // Waypoint
|
||||
|
||||
// String Code for the Display name of the Level
|
||||
LevelDisplayName string // LevelName
|
||||
@ -351,14 +351,14 @@ type LevelDetailsRecord struct {
|
||||
|
||||
// this field uses the ID of the ObjectGroup you want to Spawn in this Area,
|
||||
// taken from Objgroup.txt.
|
||||
ObjectGroupId0 int // ObjGrp0
|
||||
ObjectGroupId1 int // ObjGrp1
|
||||
ObjectGroupId2 int // ObjGrp2
|
||||
ObjectGroupId3 int // ObjGrp3
|
||||
ObjectGroupId4 int // ObjGrp4
|
||||
ObjectGroupId5 int // ObjGrp5
|
||||
ObjectGroupId6 int // ObjGrp6
|
||||
ObjectGroupId7 int // ObjGrp7
|
||||
ObjectGroupID0 int // ObjGrp0
|
||||
ObjectGroupID1 int // ObjGrp1
|
||||
ObjectGroupID2 int // ObjGrp2
|
||||
ObjectGroupID3 int // ObjGrp3
|
||||
ObjectGroupID4 int // ObjGrp4
|
||||
ObjectGroupID5 int // ObjGrp5
|
||||
ObjectGroupID6 int // ObjGrp6
|
||||
ObjectGroupID7 int // ObjGrp7
|
||||
|
||||
// These fields indicates the chance for each object group to spawn (if you
|
||||
// use ObjGrp0 then set ObjPrb0 to a value below 100)
|
||||
@ -387,6 +387,7 @@ func GetLevelDetails(id int) *LevelDetailsRecord {
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint:funlen // Txt loader, makes no sense to split
|
||||
func LoadLevelDetails(file []byte) {
|
||||
dict := d2common.LoadDataDictionary(string(file))
|
||||
numRecords := len(dict.Data)
|
||||
@ -425,22 +426,22 @@ func LoadLevelDetails(file []byte) {
|
||||
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),
|
||||
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),
|
||||
@ -449,7 +450,7 @@ func LoadLevelDetails(file []byte) {
|
||||
PortalRepositionEnable: dict.GetNumber("Position", idx) > 0,
|
||||
SaveMonsterStates: dict.GetNumber("SaveMonsters", idx) > 0,
|
||||
SaveMerchantStates: dict.GetNumber("SaveMonsters", idx) > 0,
|
||||
QuestId: dict.GetNumber("Quest", idx),
|
||||
QuestID: dict.GetNumber("Quest", idx),
|
||||
WarpClearanceDistance: dict.GetNumber("WarpDist", idx),
|
||||
MonsterLevelNormal: dict.GetNumber("MonLvl1", idx),
|
||||
MonsterLevelNightmare: dict.GetNumber("MonLvl2", idx),
|
||||
@ -469,68 +470,68 @@ func LoadLevelDetails(file []byte) {
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
@ -542,5 +543,6 @@ func LoadLevelDetails(file []byte) {
|
||||
}
|
||||
LevelDetails[idx] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d LevelDetails records", len(LevelDetails))
|
||||
}
|
||||
|
@ -9,9 +9,11 @@ import (
|
||||
func MapHeaders(line string) map[string]int {
|
||||
m := make(map[string]int)
|
||||
r := strings.Split(line, "\t")
|
||||
|
||||
for index, header := range r {
|
||||
m[header] = index
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@ -20,6 +22,7 @@ func MapLoadInt(r *[]string, mapping *map[string]int, field string) int {
|
||||
if ok {
|
||||
return d2common.StringToInt(d2common.EmptyToZero(d2common.AsterToEmpty((*r)[index])))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -28,6 +31,7 @@ func MapLoadString(r *[]string, mapping *map[string]int, field string) string {
|
||||
if ok {
|
||||
return d2common.AsterToEmpty((*r)[index])
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -40,5 +44,6 @@ func MapLoadUint8(r *[]string, mapping *map[string]int, field string) uint8 {
|
||||
if ok {
|
||||
return d2common.StringToUint8(d2common.EmptyToZero(d2common.AsterToEmpty((*r)[index])))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
@ -109,8 +109,10 @@ type MissileRecord struct {
|
||||
|
||||
UseAttackRating bool // if true, uses 'attack rating' to determine if it hits or misses
|
||||
// if false, has a 95% chance to hit.
|
||||
AlwaysExplode bool // if true, always calls its collision function when it is destroyed, even if it doesn't hit anything
|
||||
// note that some collision functions (lightning fury) seem to ignore this and always explode regardless of setting (requires investigation)
|
||||
AlwaysExplode bool // if true, always calls its collision function when it is destroyed,
|
||||
// even if it doesn't hit anything
|
||||
// note that some collision functions (lightning fury)
|
||||
// seem to ignore this and always explode regardless of setting (requires investigation)
|
||||
|
||||
ClientExplosion bool // if true, does not really exist
|
||||
// is only aesthetic / client side
|
||||
@ -286,21 +288,26 @@ func createMissileRecord(line string) MissileRecord {
|
||||
ClientSubMissile: [3]string{r[inc()], r[inc()], r[inc()]},
|
||||
ClientHitSubMissile: [4]string{r[inc()], r[inc()], r[inc()], r[inc()]},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
var Missiles map[int]*MissileRecord
|
||||
|
||||
func LoadMissiles(file []byte) {
|
||||
Missiles = make(map[int]*MissileRecord)
|
||||
data := strings.Split(string(file), "\r\n")[1:]
|
||||
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
rec := createMissileRecord(line)
|
||||
Missiles[rec.Id] = &rec
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d missiles", len(Missiles))
|
||||
}
|
||||
|
||||
@ -309,6 +316,7 @@ func loadMissileCalcParam(r *[]string, inc func() int) MissileCalcParam {
|
||||
Param: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
Desc: (*r)[inc()],
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -318,9 +326,11 @@ func loadMissileCalc(r *[]string, inc func() int, params int) MissileCalc {
|
||||
Desc: (*r)[inc()],
|
||||
}
|
||||
result.Params = make([]MissileCalcParam, params)
|
||||
|
||||
for p := 0; p < params; p++ {
|
||||
result.Params[p] = loadMissileCalcParam(r, inc)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -332,6 +342,7 @@ func loadMissileLight(r *[]string, inc func() int) MissileLight {
|
||||
Green: d2common.StringToUint8(d2common.EmptyToZero((*r)[inc()])),
|
||||
Blue: d2common.StringToUint8(d2common.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -349,6 +360,7 @@ func loadMissileAnimation(r *[]string, inc func() int) MissileAnimation {
|
||||
SubStartingFrame: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
SubEndingFrame: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -364,6 +376,7 @@ func loadMissileCollision(r *[]string, inc func() int) MissileCollision {
|
||||
UseCollisionTimer: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])) == 1,
|
||||
TimerFrames: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -387,6 +400,7 @@ func loadMissileDamage(r *[]string, inc func() int) MissileDamage {
|
||||
},
|
||||
DamageSynergyPerCalc: d2common.CalcString((*r)[inc()]),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -401,5 +415,6 @@ func loadMissileElementalDamage(r *[]string, inc func() int) MissileElementalDam
|
||||
d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -6,26 +6,32 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
var MonPresets [][]string
|
||||
|
||||
func LoadMonPresets(file []byte) {
|
||||
dict := d2common.LoadDataDictionary(string(file))
|
||||
numRecords := len(dict.Data)
|
||||
MonPresets = make([][]string, numRecords)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
MonPresets[act][placeIdx] = dict.GetString("Place", dictIdx)
|
||||
placeIdx++
|
||||
lastAct = act
|
||||
|
||||
placeIdx++
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d MonPreset records", len(MonPresets))
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// d2datadict contains loaders for the txt file data
|
||||
package d2datadict
|
||||
|
||||
import (
|
||||
@ -37,7 +38,7 @@ type MonStatsRecord struct {
|
||||
|
||||
// this is the actual internal ID of the unit (this is what the ID pointer
|
||||
// actually points at) remember that no two units can have the same ID,
|
||||
// this will result in lots of unpredictable behaviour and crashes so please
|
||||
// this will result in lots of unpredictable behavior and crashes so please
|
||||
// don’t do it. This 'HarcCodedInDeX' is used for several things, such as
|
||||
// determining whenever the unit uses DCC or DC6 graphics (like mephisto
|
||||
// and the death animations of Diablo, the Maggoc Queen etc.), the hcIdx
|
||||
@ -49,8 +50,8 @@ type MonStatsRecord struct {
|
||||
// this column contains the ID pointer of the “base” unit for this specific
|
||||
// monster type (ex. There are five types of “Fallen”; all of them have
|
||||
// fallen1 as their “base” unit). The baseID is responsible for some
|
||||
// hardcoded behaviours, for example moving thru walls (ghosts), knowing
|
||||
// what units to ressurect, create etc (putrid defilers, shamans etc), the
|
||||
// hardcoded behaviors, for example moving thru walls (ghosts), knowing
|
||||
// what units to resurrect, create etc (putrid defilers, shamans etc), the
|
||||
// explosion appended to suicide minions (either cold, fire or ice). Thanks
|
||||
// to Kingpin for additional info on this column.
|
||||
BaseKey string // BaseId
|
||||
@ -312,7 +313,7 @@ type MonStatsRecord struct {
|
||||
// these columns control “non-skill-related” missiles used by the monster.
|
||||
// For example if you enter a missile ID pointer (from Missiles.txt) in
|
||||
// MissA1 then, whenever the monster uses its A1 mode, it will shoot a
|
||||
// missile, this however will succesfully prevent it from dealing any damage
|
||||
// missile, this however will successfully prevent it from dealing any damage
|
||||
// with the swing of A1.
|
||||
// NOTE: for the beginners, A1=Attack1, A2=Attack2, S1=Skill1, S2=Skill2,
|
||||
// S3=Skill3, S4=Skill4, C=Cast, SQ=Sequence.
|
||||
@ -389,7 +390,7 @@ type MonStatsRecord struct {
|
||||
// Boolean, 1=I can open doors, 0=I’m too damn retarded to open doors. Ever
|
||||
// wanted to make the game more like D1 (where closing doors could actually
|
||||
// protect you), then this column is all you need. By setting this to 0 you
|
||||
// will succesfully lobotomize the monster, thus he will not be able to open
|
||||
// will successfully lobotomize the monster, thus he will not be able to open
|
||||
// doors any more.
|
||||
CanOpenDoors bool // opendoors
|
||||
|
||||
@ -793,10 +794,12 @@ type MonStatsRecord struct {
|
||||
|
||||
var MonStats map[string]*MonStatsRecord
|
||||
|
||||
//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)
|
||||
|
||||
for idx := range dict.Data {
|
||||
record := &MonStatsRecord{
|
||||
Key: dict.GetString("Id", idx),
|
||||
@ -1054,5 +1057,6 @@ func LoadMonStats(file []byte) {
|
||||
}
|
||||
MonStats[record.Key] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d MonStats records", len(MonStats))
|
||||
}
|
||||
|
369
d2common/d2data/d2datadict/monstats2.go
Normal file
369
d2common/d2data/d2datadict/monstats2.go
Normal file
@ -0,0 +1,369 @@
|
||||
package d2datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
)
|
||||
|
||||
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
|
||||
TRv []string
|
||||
LGv []string
|
||||
Rav []string
|
||||
Lav []string
|
||||
RHv []string
|
||||
LHv []string
|
||||
SHv []string
|
||||
S1v []string
|
||||
S2v []string
|
||||
S3v []string
|
||||
S4v []string
|
||||
S5v []string
|
||||
S6v []string
|
||||
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
|
||||
|
||||
// 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
|
||||
dWL int
|
||||
dGH int
|
||||
dA1 int
|
||||
dA2 int
|
||||
dBL int
|
||||
dSC int
|
||||
dS1 int
|
||||
dS2 int
|
||||
dS3 int
|
||||
dS4 int
|
||||
dDD int
|
||||
dKB int
|
||||
dSQ int
|
||||
dRN int
|
||||
|
||||
// Available modes while moving aside from WL and RN
|
||||
A1mv bool
|
||||
A2mv bool
|
||||
SCmv bool
|
||||
S1mv bool
|
||||
S2mv bool
|
||||
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
|
||||
|
||||
// If the units can use overlays
|
||||
NoOvly bool
|
||||
|
||||
// If unit is selectable
|
||||
IsSelectable bool
|
||||
|
||||
// If unit is selectable by allies
|
||||
AllySelectable bool
|
||||
|
||||
// If unit is not selectable
|
||||
NotSelectable bool
|
||||
|
||||
// Kinda unk, used for bonewalls etc that are not properly selectable
|
||||
shiftSel bool
|
||||
|
||||
// if the units corpse is selectable
|
||||
IsCorpseSelectable bool
|
||||
|
||||
// If the unit is attackable
|
||||
IsAttackable bool
|
||||
|
||||
// If the unit is revivable
|
||||
IsRevivable bool
|
||||
|
||||
// If the unit is a critter
|
||||
IsCritter bool
|
||||
|
||||
// If the unit is Small, Small units can be knocked back with 100% efficiency
|
||||
IsSmall bool
|
||||
|
||||
// Large units can be knocked back at 25% efficincy
|
||||
IsLarge bool
|
||||
|
||||
// Possibly to do with sound, usually set for creatures without flesh
|
||||
IsSoft bool
|
||||
|
||||
// Aggressive or harmless, usually NPC's
|
||||
IsInert bool
|
||||
|
||||
// Unknown
|
||||
objCol bool
|
||||
|
||||
// Enables collision on corpse for units
|
||||
IsCorpseCollidable bool
|
||||
|
||||
// Can the corpse be walked through
|
||||
IsCorpseWalkable bool
|
||||
|
||||
// If the unit casts a shadow
|
||||
HasShadow bool
|
||||
|
||||
// If unique palettes should not be used
|
||||
NoUniqueShift bool
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Current design issue
|
||||
var MonStats2 map[string]MonStats2Record
|
||||
|
||||
//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)
|
||||
|
||||
for idx := range dict.Data {
|
||||
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("RDv", 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),
|
||||
}
|
||||
MonStats2[record.Key] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d MonStats2 records", len(MonStats2))
|
||||
}
|
@ -49,6 +49,7 @@ func LookupObject(act, typ, id int) *ObjectLookupRecord {
|
||||
if object == nil {
|
||||
log.Panicf("Failed to look up object Act: %d, Type: %d, Id: %d", act, typ, id)
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
@ -56,6 +57,7 @@ func lookupObject(act, typ, id int, objects [][][]*ObjectLookupRecord) *ObjectLo
|
||||
if objects[act] != nil && objects[act][typ] != nil && objects[act][typ][id] != nil {
|
||||
return objects[act][typ][id]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -66,6 +68,7 @@ func init() {
|
||||
func indexObjects(objects []ObjectLookupRecord) [][][]*ObjectLookupRecord {
|
||||
// Allocating 6 to allow Acts 1-5 without requiring a -1 at every read.
|
||||
indexedObjects = make([][][]*ObjectLookupRecord, 6)
|
||||
|
||||
for i := range objects {
|
||||
record := &objects[i]
|
||||
if indexedObjects[record.Act] == nil {
|
||||
|
@ -12,12 +12,15 @@ type ObjectTypeRecord struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
// ObjectTypes contains the name and token for objects
|
||||
var ObjectTypes []ObjectTypeRecord
|
||||
|
||||
func LoadObjectTypes(objectTypeData []byte) {
|
||||
streamReader := d2common.CreateStreamReader(objectTypeData)
|
||||
count := streamReader.GetInt32()
|
||||
ObjectTypes = make([]ObjectTypeRecord, count)
|
||||
|
||||
for i := range ObjectTypes {
|
||||
nameBytes := streamReader.ReadBytes(32)
|
||||
tokenBytes := streamReader.ReadBytes(20)
|
||||
@ -26,5 +29,6 @@ func LoadObjectTypes(objectTypeData []byte) {
|
||||
Token: strings.TrimSpace(strings.ReplaceAll(string(tokenBytes), string(0), "")),
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d object types", len(ObjectTypes))
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ type ObjectRecord struct {
|
||||
// 0 = it doesn't, rest of modes need to be analyzed
|
||||
}
|
||||
|
||||
//nolint:funlen // Makes no sense to split
|
||||
// CreateObjectRecord parses a row from objects.txt into an object record
|
||||
func createObjectRecord(props []string) ObjectRecord {
|
||||
i := -1
|
||||
@ -330,24 +331,31 @@ func createObjectRecord(props []string) ObjectRecord {
|
||||
|
||||
AutoMap: d2common.StringToInt(props[inc()]),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
var Objects map[int]*ObjectRecord
|
||||
|
||||
func LoadObjects(file []byte) {
|
||||
Objects = make(map[int]*ObjectRecord)
|
||||
data := strings.Split(string(file), "\r\n")[1:]
|
||||
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
props := strings.Split(line, "\t")
|
||||
|
||||
if props[2] == "" {
|
||||
continue // skip a line that doesn't have an id
|
||||
}
|
||||
|
||||
rec := createObjectRecord(props)
|
||||
Objects[rec.Id] = &rec
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d objects", len(Objects))
|
||||
}
|
||||
|
@ -71,21 +71,27 @@ func createSoundEntry(soundLine string) SoundEntry {
|
||||
Block2: d2common.StringToInt(props[inc()]),
|
||||
Block3: d2common.StringToInt(props[inc()]),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||
var Sounds map[string]SoundEntry
|
||||
|
||||
func LoadSounds(file []byte) {
|
||||
Sounds = make(map[string]SoundEntry)
|
||||
soundData := strings.Split(string(file), "\r\n")[1:]
|
||||
|
||||
for _, line := range soundData {
|
||||
if len(line) == 0 {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
soundEntry := createSoundEntry(line)
|
||||
soundEntry.FileName = "/data/global/sfx/" + strings.ReplaceAll(soundEntry.FileName, `\`, "/")
|
||||
Sounds[soundEntry.Handle] = soundEntry
|
||||
|
||||
//nolint:gocritic // Debug util code
|
||||
/*
|
||||
// Use the following code to write out the values
|
||||
f, err := os.OpenFile(`C:\Users\lunat\Desktop\D2\sounds.txt`,
|
||||
@ -98,6 +104,7 @@ func LoadSounds(file []byte) {
|
||||
log.Println(err)
|
||||
}
|
||||
*/
|
||||
}
|
||||
} //nolint:wsl // Debug util code
|
||||
|
||||
log.Printf("Loaded %d sound definitions", len(Sounds))
|
||||
}
|
||||
|
@ -93,8 +93,10 @@ type SuperUniqueRecord struct {
|
||||
// Boolean indicates if the game is expansion or classic
|
||||
IsExpansion bool // named as "EClass" in the SuperUniques.txt
|
||||
|
||||
// This field states whether the SuperUnique will be placed within a radius from his original position(defined by the .ds1 map file), or not.
|
||||
// false means that the boss will spawn in a random position within a large radius from its actual position in the .ds1 file,
|
||||
// This field states whether the SuperUnique will be placed within a radius from his original
|
||||
// position(defined by the .ds1 map file), or not.
|
||||
// false means that the boss will spawn in a random position within a large radius from its actual
|
||||
// position in the .ds1 file,
|
||||
// true means it will spawn exactly where expected.
|
||||
AutoPosition bool
|
||||
|
||||
@ -104,7 +106,8 @@ type SuperUniqueRecord struct {
|
||||
|
||||
// Treasure Classes for the 3 Difficulties.
|
||||
// These columns list the treasureclass that is valid if this boss is killed and drops something.
|
||||
// These fields must contain the values taken from the "TreasureClass" column in TreasureClassEx.txt (Expansion) or TreasureClass (Classic).
|
||||
// These fields must contain the values taken from the "TreasureClass" column in TreasureClassEx.txt (Expansion)
|
||||
// or TreasureClass (Classic).
|
||||
TreasureClassNormal string
|
||||
TreasureClassNightmare string
|
||||
TreasureClassHell string
|
||||
@ -120,6 +123,7 @@ var SuperUniques map[string]*SuperUniqueRecord
|
||||
func LoadSuperUniques(file []byte) {
|
||||
dictionary := d2common.LoadDataDictionary(string(file))
|
||||
SuperUniques = make(map[string]*SuperUniqueRecord, len(dictionary.Data))
|
||||
|
||||
for idx := range dictionary.Data {
|
||||
record := &SuperUniqueRecord{
|
||||
Key: dictionary.GetString("Superunique", idx),
|
||||
@ -146,5 +150,6 @@ func LoadSuperUniques(file []byte) {
|
||||
}
|
||||
SuperUniques[record.Key] = record
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d SuperUnique records", len(SuperUniques))
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ func createUniqueItemRecord(r []string) UniqueItemRecord {
|
||||
createUniqueItemProperty(&r, inc),
|
||||
},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -109,6 +110,7 @@ func createUniqueItemProperty(r *[]string, inc func() int) UniqueItemProperty {
|
||||
Min: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
Max: d2common.StringToInt(d2common.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -117,17 +119,21 @@ var UniqueItems map[string]*UniqueItemRecord
|
||||
func LoadUniqueItems(file []byte) {
|
||||
UniqueItems = make(map[string]*UniqueItemRecord)
|
||||
data := strings.Split(string(file), "\r\n")[1:]
|
||||
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
r := strings.Split(line, "\t")
|
||||
// skip rows that are not enabled
|
||||
if r[2] != "1" {
|
||||
continue
|
||||
}
|
||||
|
||||
rec := createUniqueItemRecord(r)
|
||||
UniqueItems[rec.Code] = &rec
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d unique items", len(UniqueItems))
|
||||
}
|
||||
|
57
d2common/d2enum/monsteranimationmode_string2enum.go
Normal file
57
d2common/d2enum/monsteranimationmode_string2enum.go
Normal file
@ -0,0 +1,57 @@
|
||||
// Manually edited to remove duplicate
|
||||
// If you generate it again you need fix it up
|
||||
|
||||
// Code generated by "string2enum -samepkg -linecomment -type MonsterAnimationMode ."; DO NOT EDIT.
|
||||
|
||||
package d2enum
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MonsterAnimationModeFromString returns the MonsterAnimationMode enum corresponding to s.
|
||||
func MonsterAnimationModeFromString(s string) MonsterAnimationMode {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
for i := range _MonsterAnimationMode_index[:len(_MonsterAnimationMode_index)-1] {
|
||||
if s == _MonsterAnimationMode_name[_MonsterAnimationMode_index[i]:_MonsterAnimationMode_index[i+1]] {
|
||||
return MonsterAnimationMode(i)
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("unable to locate MonsterAnimationMode enum corresponding to %q", s))
|
||||
}
|
||||
|
||||
func _(s string) {
|
||||
// Check for duplicate string values in type "MonsterAnimationMode".
|
||||
switch s {
|
||||
// 0
|
||||
case "DT":
|
||||
// 1
|
||||
case "NU":
|
||||
// 2
|
||||
case "WL":
|
||||
// 3
|
||||
case "GH":
|
||||
// 4
|
||||
case "A1":
|
||||
// 5
|
||||
case "A2":
|
||||
// 6
|
||||
case "BL":
|
||||
// 7
|
||||
case "SC":
|
||||
// 8
|
||||
case "S1":
|
||||
// 9
|
||||
case "S2":
|
||||
// 10
|
||||
case "S3":
|
||||
// 11
|
||||
case "S4":
|
||||
// 12
|
||||
case "DD":
|
||||
// 14
|
||||
case "xx":
|
||||
// 15
|
||||
case "RN":
|
||||
}
|
||||
}
|
@ -279,6 +279,7 @@ const (
|
||||
// --- Enemy Data ---
|
||||
|
||||
MonStats = "/data/global/excel/monstats.txt"
|
||||
MonStats2 = "/data/global/excel/monstats2.txt"
|
||||
MonPreset = "/data/global/excel/monpreset.txt"
|
||||
SuperUniques = "/data/global/excel/SuperUniques.txt"
|
||||
|
||||
|
@ -47,3 +47,15 @@ func (v *DataDictionary) GetNumber(fieldName string, index int) int {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *DataDictionary) GetDelimitedList(fieldName string, index int) []string {
|
||||
return strings.Split(v.GetString(fieldName, index), ",")
|
||||
}
|
||||
|
||||
func (v *DataDictionary) GetBool(fieldName string, index int) bool {
|
||||
n := v.GetNumber(fieldName, index)
|
||||
if n > 1 {
|
||||
log.Panic("GetBool on non-bool field")
|
||||
}
|
||||
return n == 1
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func CreateMapRenderer(mapEngine *d2mapengine.MapEngine, term d2interface.Termin
|
||||
result.debugVisLevel = level
|
||||
})
|
||||
|
||||
if mapEngine.LevelType().Id != 0 {
|
||||
if mapEngine.LevelType().ID != 0 {
|
||||
result.generateTileCache()
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func (mr *MapRenderer) generateTileCache() {
|
||||
mr.palette, _ = loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().Id))
|
||||
mr.palette, _ = loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
|
||||
mapEngineSize := mr.mapEngine.Size()
|
||||
|
||||
for idx, tile := range *mr.mapEngine.Tiles() {
|
||||
@ -197,7 +197,7 @@ func (mr *MapRenderer) getRandomTile(tiles []d2dt1.Tile, x, y int, seed int64) b
|
||||
|
||||
var tileSeed uint64
|
||||
tileSeed = uint64(seed) + uint64(x)
|
||||
tileSeed *= uint64(y) + uint64(mr.mapEngine.LevelType().Id)
|
||||
tileSeed *= uint64(y) + uint64(mr.mapEngine.LevelType().ID)
|
||||
|
||||
tileSeed ^= tileSeed << 13
|
||||
tileSeed ^= tileSeed >> 17
|
||||
|
1
main.go
1
main.go
@ -431,6 +431,7 @@ func loadDataDict() error {
|
||||
{d2resource.SoundSettings, d2datadict.LoadSounds},
|
||||
{d2resource.AnimationData, d2data.LoadAnimationData},
|
||||
{d2resource.MonStats, d2datadict.LoadMonStats},
|
||||
{d2resource.MonStats2, d2datadict.LoadMonStats2},
|
||||
{d2resource.MonPreset, d2datadict.LoadMonPresets},
|
||||
{d2resource.MagicPrefix, d2datadict.LoadMagicPrefix},
|
||||
{d2resource.MagicSuffix, d2datadict.LoadMagicSuffix},
|
||||
|
Loading…
x
Reference in New Issue
Block a user