From 4a62101b96ebf58facd7a317796d08f332cad69a Mon Sep 17 00:00:00 2001 From: gravestench Date: Wed, 28 Oct 2020 17:52:15 +0000 Subject: [PATCH] adding the rest of the data dictionary loaders (#869) --- d2common/d2resource/resource_paths.go | 12 ++- d2core/d2asset/asset_manager.go | 14 ++- d2core/d2asset/composite.go | 2 +- d2core/d2item/diablo2item/item_factory.go | 2 +- d2core/d2records/armor_type_loader.go | 30 ++++++ d2core/d2records/armor_type_record.go | 11 +++ d2core/d2records/composite_type_loader.go | 30 ++++++ d2core/d2records/composite_type_record.go | 11 +++ d2core/d2records/cube_modifier_loader.go | 30 ++++++ d2core/d2records/cube_modifier_record.go | 10 ++ d2core/d2records/cube_type_loader.go | 30 ++++++ d2core/d2records/cube_type_record.go | 10 ++ d2core/d2records/cubemain_loader.go | 2 +- .../d2records/hireling_description_loader.go | 30 ++++++ .../d2records/hireling_description_record.go | 10 ++ d2core/d2records/hireling_loader.go | 2 +- d2core/d2records/hit_class_loader.go | 30 ++++++ d2core/d2records/hit_class_record.go | 10 ++ d2core/d2records/item_low_quality_loader.go | 29 ++++++ d2core/d2records/item_low_quality_record.go | 9 ++ .../d2records/monster_unique_affix_loader.go | 99 +++++++++++++++++++ .../d2records/monster_unique_affix_record.go | 23 +++++ d2core/d2records/player_type_loader.go | 34 +++++++ d2core/d2records/player_type_record.go | 10 ++ d2core/d2records/record_manager.go | 66 ++++++++++--- d2core/d2records/treasure_class_loader.go | 37 +++++-- d2core/d2records/weapon_class_loader.go | 30 ++++++ d2core/d2records/weapon_class_record.go | 11 +++ go.mod | 1 + go.sum | 2 + 30 files changed, 596 insertions(+), 31 deletions(-) create mode 100644 d2core/d2records/armor_type_loader.go create mode 100644 d2core/d2records/armor_type_record.go create mode 100644 d2core/d2records/composite_type_loader.go create mode 100644 d2core/d2records/composite_type_record.go create mode 100644 d2core/d2records/cube_modifier_loader.go create mode 100644 d2core/d2records/cube_modifier_record.go create mode 100644 d2core/d2records/cube_type_loader.go create mode 100644 d2core/d2records/cube_type_record.go create mode 100644 d2core/d2records/hireling_description_loader.go create mode 100644 d2core/d2records/hireling_description_record.go create mode 100644 d2core/d2records/hit_class_loader.go create mode 100644 d2core/d2records/hit_class_record.go create mode 100644 d2core/d2records/item_low_quality_loader.go create mode 100644 d2core/d2records/item_low_quality_record.go create mode 100644 d2core/d2records/monster_unique_affix_loader.go create mode 100644 d2core/d2records/monster_unique_affix_record.go create mode 100644 d2core/d2records/player_type_loader.go create mode 100644 d2core/d2records/player_type_record.go create mode 100644 d2core/d2records/weapon_class_loader.go create mode 100644 d2core/d2records/weapon_class_record.go diff --git a/d2common/d2resource/resource_paths.go b/d2common/d2resource/resource_paths.go index 46d9ec76..19011df5 100644 --- a/d2common/d2resource/resource_paths.go +++ b/d2common/d2resource/resource_paths.go @@ -194,6 +194,7 @@ const ( ItemRatio = "/data/global/excel/itemratio.txt" ItemTypes = "/data/global/excel/ItemTypes.txt" QualityItems = "/data/global/excel/qualityitems.txt" + LowQualityItems = "/data/global/excel/lowqualityitems.txt" Overlays = "/data/global/excel/Overlay.txt" Runes = "/data/global/excel/runes.txt" Sets = "/data/global/excel/Sets.txt" @@ -203,14 +204,18 @@ const ( Events = "/data/global/excel/events.txt" Properties = "/data/global/excel/Properties.txt" Hireling = "/data/global/excel/hireling.txt" + HirelingDescription = "/data/global/excel/HireDesc.txt" DifficultyLevels = "/data/global/excel/difficultylevels.txt" AutoMap = "/data/global/excel/AutoMap.txt" CubeRecipes = "/data/global/excel/cubemain.txt" + CubeModifier = "/data/global/excel/CubeMod.txt" + CubeType = "/data/global/excel/CubeType.txt" Skills = "/data/global/excel/skills.txt" SkillDesc = "/data/global/excel/skilldesc.txt" SkillCalc = "/data/global/excel/skillcalc.txt" MissileCalc = "/data/global/excel/misscalc.txt" - TreasureClass = "/data/global/excel/TreasureClassEx.txt" + TreasureClass = "/data/global/excel/TreasureClass.txt" + TreasureClassEx = "/data/global/excel/TreasureClassEx.txt" States = "/data/global/excel/states.txt" SoundEnvirons = "/data/global/excel/soundenviron.txt" Shrines = "/data/global/excel/shrines.txt" @@ -226,6 +231,9 @@ const ( MonsterSound = "/data/global/excel/monsounds.txt" MonsterSequence = "/data/global/excel/monseq.txt" PlayerClass = "/data/global/excel/PlayerClass.txt" + PlayerType = "/data/global/excel/PlrType.txt" + Composite = "/data/global/excel/Composit.txt" + HitClass = "/data/global/excel/HitClass.txt" ObjectGroup = "/data/global/excel/objgroup.txt" CompCode = "/data/global/excel/compcode.txt" Belts = "/data/global/excel/belts.txt" @@ -246,6 +254,8 @@ const ( Inventory = "/data/global/excel/inventory.txt" Weapons = "/data/global/excel/weapons.txt" Armor = "/data/global/excel/armor.txt" + ArmorType = "/data/global/excel/ArmType.txt" + WeaponClass = "/data/global/excel/WeaponClass.txt" Books = "/data/global/excel/books.txt" Misc = "/data/global/excel/misc.txt" UniqueItems = "/data/global/excel/UniqueItems.txt" diff --git a/d2core/d2asset/asset_manager.go b/d2core/d2asset/asset_manager.go index 77e06f64..6121f1d0 100644 --- a/d2core/d2asset/asset_manager.go +++ b/d2core/d2asset/asset_manager.go @@ -115,6 +115,7 @@ func (am *AssetManager) initDataDictionaries() error { d2resource.SetItems, d2resource.AutoMagic, d2resource.TreasureClass, + d2resource.TreasureClassEx, d2resource.States, d2resource.SoundEnvirons, d2resource.Shrines, @@ -137,6 +138,17 @@ func (am *AssetManager) initDataDictionaries() error { d2resource.RareSuffix, d2resource.Events, d2resource.Colors, + d2resource.ArmorType, + d2resource.WeaponClass, + d2resource.PlayerType, + d2resource.Composite, + d2resource.HitClass, + d2resource.UniquePrefix, + d2resource.UniqueSuffix, + d2resource.CubeModifier, + d2resource.CubeType, + d2resource.HirelingDescription, + d2resource.LowQualityItems, } for _, path := range dictPaths { @@ -440,7 +452,7 @@ func (am *AssetManager) initAnimationData(path string) error { animData := d2data.LoadAnimationData(animDataBytes) - am.Records.Animations = animData + am.Records.Animation.Data = animData return nil } diff --git a/d2core/d2asset/composite.go b/d2core/d2asset/composite.go index d81a139e..d2281068 100644 --- a/d2core/d2asset/composite.go +++ b/d2core/d2asset/composite.go @@ -259,7 +259,7 @@ func (c *Composite) createMode(animationMode animationMode, weaponClass string) animationKey := strings.ToLower(c.token + animationMode.String() + weaponClass) - animationData := c.Records.Animations[animationKey] + animationData := c.Records.Animation.Data[animationKey] if len(animationData) == 0 { return nil, errors.New("could not find Animation data") } diff --git a/d2core/d2item/diablo2item/item_factory.go b/d2core/d2item/diablo2item/item_factory.go index 95a2988e..b6f8479e 100644 --- a/d2core/d2item/diablo2item/item_factory.go +++ b/d2core/d2item/diablo2item/item_factory.go @@ -260,7 +260,7 @@ func (f *ItemFactory) ItemsFromTreasureClass(tcr *d2records.TreasureClassRecord) // case we will roll that treasure class, eventually getting a slice of items for idx := range treasurePicks { picked := treasurePicks[idx] - if record, found := f.asset.Records.Item.TreasureClass[picked.Code]; found { + if record, found := f.asset.Records.Item.Treasure.Normal[picked.Code]; found { // the code is for a treasure class, we roll again using that TC itemSlice := f.ItemsFromTreasureClass(record) for itemIdx := range itemSlice { diff --git a/d2core/d2records/armor_type_loader.go b/d2core/d2records/armor_type_loader.go new file mode 100644 index 00000000..8f66fd8e --- /dev/null +++ b/d2core/d2records/armor_type_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func armorTypesLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(ArmorTypes) + + for d.Next() { + record := &ArmorTypeRecord{ + Name: d.String("Name"), + Token: d.String("Token"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Animation.Token.Armor = records + + log.Printf("Loaded %d ArmorType records", len(records)) + + return nil +} diff --git a/d2core/d2records/armor_type_record.go b/d2core/d2records/armor_type_record.go new file mode 100644 index 00000000..a565f690 --- /dev/null +++ b/d2core/d2records/armor_type_record.go @@ -0,0 +1,11 @@ +package d2records + +// ArmorTypes is a map of ArmorTypeRecords +type ArmorTypes map[string]*ArmorTypeRecord + +// ArmorTypeRecord describes an armor type. It has a name and 3-character token. +// The token is used to change the character animation mode. +type ArmorTypeRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/composite_type_loader.go b/d2core/d2records/composite_type_loader.go new file mode 100644 index 00000000..e9ca6ed1 --- /dev/null +++ b/d2core/d2records/composite_type_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func compositeTypeLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(CompositeTypes) + + for d.Next() { + record := &CompositeTypeRecord{ + Name: d.String("Name"), + Token: d.String("Token"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Animation.Token.Composite = records + + log.Printf("Loaded %d Composite Type records", len(records)) + + return nil +} diff --git a/d2core/d2records/composite_type_record.go b/d2core/d2records/composite_type_record.go new file mode 100644 index 00000000..8b038d72 --- /dev/null +++ b/d2core/d2records/composite_type_record.go @@ -0,0 +1,11 @@ +package d2records + +// CompositeTypes is a map of CompositeTypeRecords +type CompositeTypes map[string]*CompositeTypeRecord + +// CompositeTypeRecord describes a layer for an animated composite (multi-sprite entities). +// The token is used for changing character animation modes. +type CompositeTypeRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/cube_modifier_loader.go b/d2core/d2records/cube_modifier_loader.go new file mode 100644 index 00000000..7ffa89f5 --- /dev/null +++ b/d2core/d2records/cube_modifier_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func cubeModifierLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(CubeModifiers) + + for d.Next() { + record := &CubeModifierRecord{ + Name: d.String("cube modifier type"), + Token: d.String("Code"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Item.Cube.Modifiers = records + + log.Printf("Loaded %d Cube Modifier records", len(records)) + + return nil +} diff --git a/d2core/d2records/cube_modifier_record.go b/d2core/d2records/cube_modifier_record.go new file mode 100644 index 00000000..a857210a --- /dev/null +++ b/d2core/d2records/cube_modifier_record.go @@ -0,0 +1,10 @@ +package d2records + +// CubeModifiers is a map of CubeModifierRecords +type CubeModifiers map[string]*CubeModifierRecord + +// CubeModifierRecord is a name and 3-character token for cube modifier codes and gem types +type CubeModifierRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/cube_type_loader.go b/d2core/d2records/cube_type_loader.go new file mode 100644 index 00000000..f3d11772 --- /dev/null +++ b/d2core/d2records/cube_type_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func cubeTypeLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(CubeTypes) + + for d.Next() { + record := &CubeTypeRecord{ + Name: d.String("cube item class"), + Token: d.String("Code"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Item.Cube.Types = records + + log.Printf("Loaded %d Cube Type records", len(records)) + + return nil +} diff --git a/d2core/d2records/cube_type_record.go b/d2core/d2records/cube_type_record.go new file mode 100644 index 00000000..8c273268 --- /dev/null +++ b/d2core/d2records/cube_type_record.go @@ -0,0 +1,10 @@ +package d2records + +// CubeTypes is a map of CubeTypeRecords +type CubeTypes map[string]*CubeTypeRecord + +// CubeTypeRecord is a name and 3-character token for cube item types +type CubeTypeRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/cubemain_loader.go b/d2core/d2records/cubemain_loader.go index a2c4374b..b5deb63a 100644 --- a/d2core/d2records/cubemain_loader.go +++ b/d2core/d2records/cubemain_loader.go @@ -85,7 +85,7 @@ func cubeRecipeLoader(r *RecordManager, d *d2txt.DataDictionary) error { log.Printf("Loaded %d CubeMainRecord records", len(records)) - r.Item.Recipes = records + r.Item.Cube.Recipes = records return nil } diff --git a/d2core/d2records/hireling_description_loader.go b/d2core/d2records/hireling_description_loader.go new file mode 100644 index 00000000..8a4acc4f --- /dev/null +++ b/d2core/d2records/hireling_description_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func hirelingDescriptionLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(HirelingDescriptions) + + for d.Next() { + record := &HirelingDescriptionRecord{ + Name: d.String("Hireling Description"), + Token: d.String("Code"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Hireling.Descriptions = records + + log.Printf("Loaded %d Hireling Descriptions records", len(records)) + + return nil +} diff --git a/d2core/d2records/hireling_description_record.go b/d2core/d2records/hireling_description_record.go new file mode 100644 index 00000000..c561da2a --- /dev/null +++ b/d2core/d2records/hireling_description_record.go @@ -0,0 +1,10 @@ +package d2records + +// HirelingDescriptions is a lookup table for hireling subtype codes +type HirelingDescriptions map[string]*HirelingDescriptionRecord + +// HirelingDescriptionRecord represents is a hireling subtype +type HirelingDescriptionRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/hireling_loader.go b/d2core/d2records/hireling_loader.go index af053759..a8b4b9d7 100644 --- a/d2core/d2records/hireling_loader.go +++ b/d2core/d2records/hireling_loader.go @@ -94,7 +94,7 @@ func hirelingLoader(r *RecordManager, d *d2txt.DataDictionary) error { log.Printf("Loaded %d Hireling records", len(records)) - r.Hirelings = records + r.Hireling.Details = records return nil } diff --git a/d2core/d2records/hit_class_loader.go b/d2core/d2records/hit_class_loader.go new file mode 100644 index 00000000..360b701b --- /dev/null +++ b/d2core/d2records/hit_class_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func hitClassLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(HitClasses) + + for d.Next() { + record := &HitClassRecord{ + Name: d.String("Hit Class"), + Token: d.String("Code"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Animation.Token.HitClass = records + + log.Printf("Loaded %d HitClass records", len(records)) + + return nil +} diff --git a/d2core/d2records/hit_class_record.go b/d2core/d2records/hit_class_record.go new file mode 100644 index 00000000..30a97b3b --- /dev/null +++ b/d2core/d2records/hit_class_record.go @@ -0,0 +1,10 @@ +package d2records + +// HitClasses is a map of HitClassRecords +type HitClasses map[string]*HitClassRecord + +// HitClassRecord is used for changing character animation modes. +type HitClassRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/item_low_quality_loader.go b/d2core/d2records/item_low_quality_loader.go new file mode 100644 index 00000000..3a3b863a --- /dev/null +++ b/d2core/d2records/item_low_quality_loader.go @@ -0,0 +1,29 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func lowQualityLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(LowQualities, 0) + + for d.Next() { + record := &LowQualityRecord{ + Name: d.String("Hireling Description"), + } + + records = append(records, record) + } + + if d.Err != nil { + panic(d.Err) + } + + r.Item.LowQualityPrefixes = records + + log.Printf("Loaded %d Low Item Quality records", len(records)) + + return nil +} diff --git a/d2core/d2records/item_low_quality_record.go b/d2core/d2records/item_low_quality_record.go new file mode 100644 index 00000000..e8bc9e4a --- /dev/null +++ b/d2core/d2records/item_low_quality_record.go @@ -0,0 +1,9 @@ +package d2records + +// LowQualities is a slice of LowQualityRecords +type LowQualities []*LowQualityRecord + +// LowQualityRecord is a name prefix that can be used for low quality item names +type LowQualityRecord struct { + Name string +} diff --git a/d2core/d2records/monster_unique_affix_loader.go b/d2core/d2records/monster_unique_affix_loader.go new file mode 100644 index 00000000..bb339cec --- /dev/null +++ b/d2core/d2records/monster_unique_affix_loader.go @@ -0,0 +1,99 @@ +package d2records + +import ( + "fmt" + "log" + + "github.com/gravestench/akara" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +// Name +// MonType1 +// MonType2 +// MonType3 +// MonType4 +// MonType5 +// MonType6 +// MonType7 +// MonType8 +// MonType9 +// MonType10 +// MonType11 +// MonType12 +// MonType13 +// MonType14 +// MonType15 +// MonType16 +// MonType17 +// MonType18 +// MonType19 +// MonType20 +// MonType21 +// MonType22 +// MonType23 +// MonType24 +// MonType25 +// MonType26 +// MonType27 +// MonType28 +// MonType29 +// MonType30 +// MonType31 +// MonType32 +// MonType33 +// MonType34 +// MonType35 +// MonType36 + +const ( + numMonsterTypes = 36 + fmtMonsterTypeColumn = "MonType%d" +) + +func uniqueMonsterPrefixLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records, err := uniqueMonsterAffixCommonLoader(d) + if err != nil { + return err + } + + r.Monster.Name.Prefix = records + + log.Printf("Loaded %d unique monster prefix records", len(records)) + + return nil +} + +func uniqueMonsterSuffixLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records, err := uniqueMonsterAffixCommonLoader(d) + if err != nil { + return err + } + + r.Monster.Name.Suffix = records + + log.Printf("Loaded %d unique monster suffix records", len(records)) + + return nil +} + +func uniqueMonsterAffixCommonLoader(d *d2txt.DataDictionary) (UniqueMonsterAffixes, error) { + records := make(UniqueMonsterAffixes) + + for d.Next() { + record := &UniqueMonsterAffixRecord{ + StringTableKey: d.String("Name"), + MonsterTypeFlags: akara.NewBitSet(), + } + + for idx := 0; idx < numMonsterTypes; idx++ { + bit := d.Number(fmt.Sprintf(fmtMonsterTypeColumn, idx)) > 0 + record.MonsterTypeFlags.Set(idx, bit) + } + + records[record.StringTableKey] = record + } + + return records, d.Err +} diff --git a/d2core/d2records/monster_unique_affix_record.go b/d2core/d2records/monster_unique_affix_record.go new file mode 100644 index 00000000..79cce869 --- /dev/null +++ b/d2core/d2records/monster_unique_affix_record.go @@ -0,0 +1,23 @@ +package d2records + +import ( + "github.com/gravestench/akara" +) + +// UniqueMonsterPrefix is a representation of a possible name prefix for a unique monster instance +// eg _Blood_ Wing the Quick +type UniqueMonsterPrefix = UniqueMonsterAffixRecord + +// UniqueMonsterSuffix is a representation of a possible name suffix for a unique monster instance. +// eg. Blood Wing _the Quick_ +type UniqueMonsterSuffix = UniqueMonsterAffixRecord + +// UniqueMonsterAffixes is a map of UniqueMonsterAffixRecords. The key is the string table lookup key. +type UniqueMonsterAffixes map[string]*UniqueMonsterAffixRecord + +// UniqueMonsterAffixRecord is a string table key and a bit vector for the possible monster types +// that the suffix can be used with. +type UniqueMonsterAffixRecord struct { + StringTableKey string + MonsterTypeFlags *akara.BitSet +} diff --git a/d2core/d2records/player_type_loader.go b/d2core/d2records/player_type_loader.go new file mode 100644 index 00000000..9155578f --- /dev/null +++ b/d2core/d2records/player_type_loader.go @@ -0,0 +1,34 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func playerTypeLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(PlayerTypes) + + for d.Next() { + record := &PlayerTypeRecord{ + Name: d.String("Player Class"), + Token: d.String("Token"), + } + + if record.Name == expansionString { + continue + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + log.Printf("Loaded %d PlayerType records", len(records)) + + r.Animation.Token.Player = records + + return nil +} diff --git a/d2core/d2records/player_type_record.go b/d2core/d2records/player_type_record.go new file mode 100644 index 00000000..81ef3b0c --- /dev/null +++ b/d2core/d2records/player_type_record.go @@ -0,0 +1,10 @@ +package d2records + +// PlayerTypes is a map of PlayerTypeRecords +type PlayerTypes map[string]*PlayerTypeRecord + +// PlayerTypeRecord is used for changing character animation modes. +type PlayerTypeRecord struct { + Name string + Token string +} diff --git a/d2core/d2records/record_manager.go b/d2core/d2records/record_manager.go index 873db806..43680700 100644 --- a/d2core/d2records/record_manager.go +++ b/d2core/d2records/record_manager.go @@ -28,7 +28,16 @@ func NewRecordManager() (*RecordManager, error) { // RecordManager stores all of the records loaded from txt files type RecordManager struct { boundLoaders map[string][]recordLoader // there can be more than one loader bound for a file - Animations d2data.AnimationData + Animation struct { + Data d2data.AnimationData + Token struct { + Player PlayerTypes + Composite CompositeTypes + Armor ArmorTypes + Weapon WeaponClasses + HitClass HitClasses + } + } BodyLocations Calculation struct { Skills Calculations @@ -47,7 +56,10 @@ type RecordManager struct { DifficultyLevels ElemTypes Gamble - Hirelings + Hireling struct { + Details Hirelings + Descriptions HirelingDescriptions + } Item struct { All CommonItems // NOTE: populated when armor, weapons, and misc items are ALL loaded @@ -66,20 +78,28 @@ type RecordManager struct { Prefix MagicPrefix Suffix MagicSuffix } - MagicPrefixGroups ItemAffixGroups - MagicSuffixGroups ItemAffixGroups - Quality ItemQualities - Rare struct { + MagicPrefixGroups ItemAffixGroups + MagicSuffixGroups ItemAffixGroups + Quality ItemQualities + LowQualityPrefixes LowQualities + Rare struct { Prefix RarePrefixes Suffix RareSuffixes } - Ratios ItemRatios - Recipes CubeRecipes + Ratios ItemRatios + Cube struct { + Recipes CubeRecipes + Modifiers CubeModifiers + Types CubeTypes + } Runewords Sets SetItems - Stats ItemStatCosts - TreasureClass + Stats ItemStatCosts + Treasure struct { + Normal TreasureClass + Expansion TreasureClass + } Types ItemTypes Unique UniqueItems StorePages @@ -100,10 +120,14 @@ type RecordManager struct { Missiles missilesByName Monster struct { - AI MonsterAI - Equipment MonsterEquipment - Levels MonsterLevels - Modes MonModes + AI MonsterAI + Equipment MonsterEquipment + Levels MonsterLevels + Modes MonModes + Name struct { + Prefix UniqueMonsterAffixes + Suffix UniqueMonsterAffixes + } Placements MonsterPlacements Presets MonPresets Props MonsterProperties @@ -140,7 +164,7 @@ type RecordManager struct { States } -func (r *RecordManager) init() error { +func (r *RecordManager) init() error { // nolint:funlen // can't reduce loaders := []struct { path string loader recordLoader @@ -198,6 +222,7 @@ func (r *RecordManager) init() error { {d2resource.SetItems, setItemLoader}, {d2resource.AutoMagic, autoMagicLoader}, {d2resource.TreasureClass, treasureClassLoader}, + {d2resource.TreasureClassEx, treasureClassExLoader}, {d2resource.States, statesLoader}, {d2resource.SoundEnvirons, soundEnvironmentLoader}, {d2resource.Shrines, shrineLoader}, @@ -219,6 +244,17 @@ func (r *RecordManager) init() error { {d2resource.RarePrefix, rareItemPrefixLoader}, {d2resource.RareSuffix, rareItemSuffixLoader}, {d2resource.Events, eventsLoader}, + {d2resource.ArmorType, armorTypesLoader}, // anim mode tokens + {d2resource.WeaponClass, weaponClassesLoader}, // anim mode tokens + {d2resource.PlayerType, playerTypeLoader}, // anim mode tokens + {d2resource.Composite, compositeTypeLoader}, // anim mode tokens + {d2resource.HitClass, hitClassLoader}, // anim mode tokens + {d2resource.UniquePrefix, uniqueMonsterPrefixLoader}, + {d2resource.UniqueSuffix, uniqueMonsterSuffixLoader}, + {d2resource.CubeModifier, cubeModifierLoader}, + {d2resource.CubeType, cubeTypeLoader}, + {d2resource.HirelingDescription, hirelingDescriptionLoader}, + {d2resource.LowQualityItems, lowQualityLoader}, } for idx := range loaders { diff --git a/d2core/d2records/treasure_class_loader.go b/d2core/d2records/treasure_class_loader.go index 056bdb20..8851893a 100644 --- a/d2core/d2records/treasure_class_loader.go +++ b/d2core/d2records/treasure_class_loader.go @@ -13,8 +13,33 @@ const ( treasureProbFmt = "Prob%d" ) -//nolint:funlen // Makes no sense to split func treasureClassLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records, err := treasureClassCommonLoader(d) + if err != nil { + return err + } + + r.Item.Treasure.Normal = records + + log.Printf("Loaded %d treasure class (normal) records", len(records)) + + return nil +} + +func treasureClassExLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records, err := treasureClassCommonLoader(d) + if err != nil { + return err + } + + r.Item.Treasure.Expansion = records + + log.Printf("Loaded %d treasure class (expansion) records", len(records)) + + return nil +} + +func treasureClassCommonLoader(d *d2txt.DataDictionary) (TreasureClass, error) { records := make(TreasureClass) for d.Next() { @@ -60,13 +85,5 @@ func treasureClassLoader(r *RecordManager, d *d2txt.DataDictionary) error { records[record.Name] = record } - if d.Err != nil { - return d.Err - } - - r.Item.TreasureClass = records - - log.Printf("Loaded %d records records", len(records)) - - return nil + return records, d.Err } diff --git a/d2core/d2records/weapon_class_loader.go b/d2core/d2records/weapon_class_loader.go new file mode 100644 index 00000000..9bbc1011 --- /dev/null +++ b/d2core/d2records/weapon_class_loader.go @@ -0,0 +1,30 @@ +package d2records + +import ( + "log" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" +) + +func weaponClassesLoader(r *RecordManager, d *d2txt.DataDictionary) error { + records := make(WeaponClasses) + + for d.Next() { + record := &WeaponClassRecord{ + Name: d.String("Weapon Class"), + Token: d.String("Code"), + } + + records[record.Name] = record + } + + if d.Err != nil { + panic(d.Err) + } + + r.Animation.Token.Weapon = records + + log.Printf("Loaded %d WeaponClass records", len(records)) + + return nil +} diff --git a/d2core/d2records/weapon_class_record.go b/d2core/d2records/weapon_class_record.go new file mode 100644 index 00000000..48f98739 --- /dev/null +++ b/d2core/d2records/weapon_class_record.go @@ -0,0 +1,11 @@ +package d2records + +// WeaponClasses is a map of WeaponClassRecords +type WeaponClasses map[string]*WeaponClassRecord + +// WeaponClassRecord describes a weapon class. It has a name and 3-character token. +// The token is used to change the character animation mode. +type WeaponClassRecord struct { + Name string + Token string +} diff --git a/go.mod b/go.mod index e4942d11..0a281e9f 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1 github.com/google/uuid v1.1.2 + github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c github.com/hajimehoshi/ebiten v1.11.4 github.com/pkg/profile v1.5.0 github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff diff --git a/go.sum b/go.sum index 44468623..d80780d7 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c h1:WopE590cKxkcKXcOee4gPXHqtzwbarLClCaWNCdLqgI= +github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ= github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgMjbJ3w7ysmD7IOU= github.com/hajimehoshi/ebiten v1.11.4 h1:ngYF0NxKjFBsY/Bol6V0X/b0hoCCTi9nJRg7Dv8+ePc= github.com/hajimehoshi/ebiten v1.11.4/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=