mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-10 18:47:23 -05:00
Switch items to dynamic load with a common struct, add misc.txt loading (#185)
This commit is contained in:
parent
0e0ad09e70
commit
f13433f299
9
d2common/calcstring.go
Normal file
9
d2common/calcstring.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package d2common
|
||||||
|
|
||||||
|
// a calcstring is a type of string often used in datafiles to specify
|
||||||
|
// a value that is calculated dynamically based on the stats of the relevant
|
||||||
|
// source, for instance a missile might have a movement speed of lvl*2
|
||||||
|
|
||||||
|
type CalcString string
|
||||||
|
|
||||||
|
// todo: the logic for parsing these should exist here
|
@ -73,6 +73,7 @@ func CreateEngine() Engine {
|
|||||||
d2datadict.LoadObjects(&result)
|
d2datadict.LoadObjects(&result)
|
||||||
d2datadict.LoadWeapons(&result)
|
d2datadict.LoadWeapons(&result)
|
||||||
d2datadict.LoadArmors(&result)
|
d2datadict.LoadArmors(&result)
|
||||||
|
d2datadict.LoadMiscItems(&result)
|
||||||
d2datadict.LoadUniqueItems(&result)
|
d2datadict.LoadUniqueItems(&result)
|
||||||
d2datadict.LoadMissiles(&result)
|
d2datadict.LoadMissiles(&result)
|
||||||
d2datadict.LoadSounds(&result)
|
d2datadict.LoadSounds(&result)
|
||||||
|
@ -2,281 +2,17 @@ package d2datadict
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
|
||||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ArmorRecord struct {
|
var Armors map[string]*ItemCommonRecord
|
||||||
Name string
|
|
||||||
|
|
||||||
Version int // 0 = classic, 100 = expansion
|
|
||||||
CompactSave bool // if true, doesn't store any stats upon saving
|
|
||||||
Rarity int // higher, the rarer
|
|
||||||
Spawnable bool // if 0, cannot spawn in shops
|
|
||||||
|
|
||||||
MinAC int
|
|
||||||
MaxAC int
|
|
||||||
Absorbs int // unused?
|
|
||||||
Speed int // affects movement speed of wielder, >0 = you move slower, <0 = you move faster
|
|
||||||
RequiredStrength int
|
|
||||||
Block int // chance to block, capped at 75%
|
|
||||||
Durability int // base durability 0-255
|
|
||||||
NoDurability bool // if true, item has no durability
|
|
||||||
|
|
||||||
Level int // base item level (controls monster drops, for instance a lv20 monster cannot drop a lv30 item)
|
|
||||||
RequiredLevel int // required level to wield
|
|
||||||
Cost int // base cost
|
|
||||||
GambleCost int // for reference only, not used
|
|
||||||
Code string // identifies the item
|
|
||||||
NameString string // seems to be identical to code?
|
|
||||||
MagicLevel int // additional magic level (for gambling?)
|
|
||||||
AutoPrefix int // prefix automatically assigned to this item on spawn, maps to group column of Automagic.txt
|
|
||||||
|
|
||||||
AlternateGfx string // code of the DCC used when equipped
|
|
||||||
OpenBetaGfx string // unknown
|
|
||||||
NormalCode string
|
|
||||||
UberCode string
|
|
||||||
UltraCode string
|
|
||||||
|
|
||||||
SpellOffset int // unknown
|
|
||||||
|
|
||||||
Component int // corresponds to Composit.txt, player animation layer used by this
|
|
||||||
InventoryWidth int
|
|
||||||
InventoryHeight int
|
|
||||||
HasInventory bool // if true, item can store gems or runes
|
|
||||||
GemSockets int // number of gems to store
|
|
||||||
GemApplyType int // what kind of gem effect is applied
|
|
||||||
// 0 = weapon, 1= armor or helmet, 2 = shield
|
|
||||||
|
|
||||||
FlippyFile string // DC6 file animation to play when item drops on the ground
|
|
||||||
InventoryFile string // DC6 file used in your inventory
|
|
||||||
UniqueInventoryFile string // DC6 file used by the unique version of this item
|
|
||||||
SetInventoryFile string // DC6 file used by the set version of this item
|
|
||||||
|
|
||||||
// these represent how player animations and graphics change upon wearing this
|
|
||||||
// these come from ArmType.txt
|
|
||||||
AnimRightArm int
|
|
||||||
AnimLeftArm int
|
|
||||||
AnimTorso int
|
|
||||||
AnimLegs int
|
|
||||||
AnimRightShoulderPad int
|
|
||||||
AnimLeftShoulderPad int
|
|
||||||
|
|
||||||
Useable bool // can be used via right click if true
|
|
||||||
// game knows what to do if used by item code
|
|
||||||
Throwable bool
|
|
||||||
Stackable bool // can be stacked in inventory
|
|
||||||
MinStack int // min size of stack when item is spawned, used if stackable
|
|
||||||
MaxStack int // max size of stack when item is spawned
|
|
||||||
|
|
||||||
Type string // base type in ItemTypes.txt
|
|
||||||
Type2 string
|
|
||||||
|
|
||||||
DropSound string // sfx for dropping
|
|
||||||
DropSfxFrame int // what frame of drop animation the sfx triggers on
|
|
||||||
UseSound string // sfx for using
|
|
||||||
|
|
||||||
Unique bool // if true, only spawns as unique
|
|
||||||
Transparent bool // unused
|
|
||||||
TransTable int // unknown, related to blending mode?
|
|
||||||
Quivered bool // if true, requires ammo to use
|
|
||||||
LightRadius int // apparently unused
|
|
||||||
Belt bool // tells what kind of belt this item is
|
|
||||||
|
|
||||||
Quest int // indicates that this item belongs to a given quest?
|
|
||||||
|
|
||||||
MissileType int // missile gfx for throwing
|
|
||||||
DurabilityWarning int // controls what warning icon appears when durability is low
|
|
||||||
QuantityWarning int // controls at what quantity the low quantity warning appears
|
|
||||||
|
|
||||||
MinDamage int
|
|
||||||
MaxDamage int
|
|
||||||
StrengthBonus int
|
|
||||||
DexterityBonus int
|
|
||||||
// final mindam = min * str / strbonus + min * dex / dexbonus
|
|
||||||
// same for maxdam
|
|
||||||
|
|
||||||
GemOffset int // unknown
|
|
||||||
BitField1 int // 1 = leather item, 3 = metal
|
|
||||||
|
|
||||||
Vendors map[string]*ItemVendorParams // controls vendor settings
|
|
||||||
|
|
||||||
SourceArt string // unused?
|
|
||||||
GameArt string // unused?
|
|
||||||
ColorTransform int // colormap to use for player's gfx
|
|
||||||
InventoryColorTransform int // colormap to use for inventory's gfx
|
|
||||||
|
|
||||||
SkipName bool // if true, don't include the base name in the item description
|
|
||||||
NightmareUpgrade string // upgraded in higher difficulties
|
|
||||||
HellUpgrade string
|
|
||||||
|
|
||||||
UnusedMinDamage int
|
|
||||||
UnusedMaxDamage int
|
|
||||||
|
|
||||||
Nameable bool // if true, item can be personalized
|
|
||||||
}
|
|
||||||
|
|
||||||
type ArmorVendorParams struct {
|
|
||||||
Min int // minimum of this item they can stock
|
|
||||||
Max int // max they can stock
|
|
||||||
MagicMin int
|
|
||||||
MagicMax int
|
|
||||||
MagicLevel uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
func createArmorRecord(line string) ArmorRecord {
|
|
||||||
r := strings.Split(line, "\t")
|
|
||||||
i := -1
|
|
||||||
inc := func() int {
|
|
||||||
i++
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
result := ArmorRecord{
|
|
||||||
Name: r[inc()],
|
|
||||||
|
|
||||||
Version: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
CompactSave: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
Rarity: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Spawnable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
|
|
||||||
MinAC: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
MaxAC: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Absorbs: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Speed: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
RequiredStrength: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Block: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Durability: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
NoDurability: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
|
|
||||||
Level: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
RequiredLevel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Cost: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
GambleCost: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Code: r[inc()],
|
|
||||||
NameString: r[inc()],
|
|
||||||
MagicLevel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AutoPrefix: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
AlternateGfx: r[inc()],
|
|
||||||
OpenBetaGfx: r[inc()],
|
|
||||||
NormalCode: r[inc()],
|
|
||||||
UberCode: r[inc()],
|
|
||||||
UltraCode: r[inc()],
|
|
||||||
|
|
||||||
SpellOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
Component: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
InventoryWidth: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
InventoryHeight: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
HasInventory: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
GemSockets: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
GemApplyType: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
FlippyFile: r[inc()],
|
|
||||||
InventoryFile: r[inc()],
|
|
||||||
UniqueInventoryFile: r[inc()],
|
|
||||||
SetInventoryFile: r[inc()],
|
|
||||||
|
|
||||||
AnimRightArm: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AnimLeftArm: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AnimTorso: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AnimLegs: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AnimRightShoulderPad: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
AnimLeftShoulderPad: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
Useable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
|
|
||||||
Throwable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
Stackable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
MinStack: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
MaxStack: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
Type: r[inc()],
|
|
||||||
Type2: r[inc()],
|
|
||||||
|
|
||||||
DropSound: r[inc()],
|
|
||||||
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
UseSound: r[inc()],
|
|
||||||
|
|
||||||
Unique: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
Transparent: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
TransTable: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Quivered: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
LightRadius: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
Belt: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
|
|
||||||
Quest: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
MissileType: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
DurabilityWarning: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
QuantityWarning: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
MinDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
MaxDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
StrengthBonus: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
DexterityBonus: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
GemOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
BitField1: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
Vendors: createArmorVendorParams(&r, inc),
|
|
||||||
|
|
||||||
SourceArt: r[inc()],
|
|
||||||
GameArt: r[inc()],
|
|
||||||
ColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
InventoryColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
SkipName: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
NightmareUpgrade: r[inc()],
|
|
||||||
HellUpgrade: r[inc()],
|
|
||||||
|
|
||||||
UnusedMinDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
UnusedMaxDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
|
||||||
|
|
||||||
Nameable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func createArmorVendorParams(r *[]string, inc func() int) map[string]*ItemVendorParams {
|
|
||||||
vs := make([]string, 17)
|
|
||||||
vs[0] = "Charsi"
|
|
||||||
vs[1] = "Gheed"
|
|
||||||
vs[2] = "Akara"
|
|
||||||
vs[3] = "Fara"
|
|
||||||
vs[4] = "Lysander"
|
|
||||||
vs[5] = "Drognan"
|
|
||||||
vs[6] = "Hralti"
|
|
||||||
vs[7] = "Alkor"
|
|
||||||
vs[8] = "Ormus"
|
|
||||||
vs[9] = "Elzix"
|
|
||||||
vs[10] = "Asheara"
|
|
||||||
vs[11] = "Cain"
|
|
||||||
vs[12] = "Halbu"
|
|
||||||
vs[13] = "Jamella"
|
|
||||||
vs[14] = "Larzuk"
|
|
||||||
vs[15] = "Malah"
|
|
||||||
vs[16] = "Drehya"
|
|
||||||
|
|
||||||
return CreateItemVendorParams(r, inc, vs)
|
|
||||||
}
|
|
||||||
|
|
||||||
var Armors map[string]*ArmorRecord
|
|
||||||
|
|
||||||
func LoadArmors(fileProvider d2interface.FileProvider) {
|
func LoadArmors(fileProvider d2interface.FileProvider) {
|
||||||
Armors = make(map[string]*ArmorRecord)
|
Armors = *LoadCommonItems(fileProvider, d2resource.Armor, d2enum.InventoryItemTypeArmor)
|
||||||
data := strings.Split(string(fileProvider.LoadFile(d2resource.Armor)), "\r\n")[1:]
|
|
||||||
for _, line := range data {
|
|
||||||
if len(line) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rec := createArmorRecord(line)
|
|
||||||
Armors[rec.Code] = &rec
|
|
||||||
}
|
|
||||||
log.Printf("Loaded %d armors", len(Armors))
|
log.Printf("Loaded %d armors", len(Armors))
|
||||||
}
|
}
|
||||||
|
416
d2data/d2datadict/item_common.go
Normal file
416
d2data/d2datadict/item_common.go
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
package d2datadict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ItemCommonRecord struct {
|
||||||
|
Source d2enum.InventoryItemType
|
||||||
|
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Version int // 0 = classic, 100 = expansion
|
||||||
|
CompactSave bool // if true, doesn't store any stats upon saving
|
||||||
|
Rarity int // higher, the rarer
|
||||||
|
Spawnable bool // if 0, cannot spawn in shops
|
||||||
|
|
||||||
|
MinAC int
|
||||||
|
MaxAC int
|
||||||
|
Absorbs int // unused?
|
||||||
|
Speed int // affects movement speed of wielder, >0 = you move slower, <0 = you move faster
|
||||||
|
RequiredStrength int
|
||||||
|
Block int // chance to block, capped at 75%
|
||||||
|
Durability int // base durability 0-255
|
||||||
|
NoDurability bool // if true, item has no durability
|
||||||
|
|
||||||
|
Level int // base item level (controls monster drops, for instance a lv20 monster cannot drop a lv30 item)
|
||||||
|
RequiredLevel int // required level to wield
|
||||||
|
Cost int // base cost
|
||||||
|
GambleCost int // for reference only, not used
|
||||||
|
Code string // identifies the item
|
||||||
|
NameString string // seems to be identical to code?
|
||||||
|
MagicLevel int // additional magic level (for gambling?)
|
||||||
|
AutoPrefix int // prefix automatically assigned to this item on spawn, maps to group column of Automagic.txt
|
||||||
|
|
||||||
|
AlternateGfx string // code of the DCC used when equipped
|
||||||
|
OpenBetaGfx string // unknown
|
||||||
|
NormalCode string
|
||||||
|
UberCode string
|
||||||
|
UltraCode string
|
||||||
|
|
||||||
|
SpellOffset int // unknown
|
||||||
|
|
||||||
|
Component int // corresponds to Composit.txt, player animation layer used by this
|
||||||
|
InventoryWidth int
|
||||||
|
InventoryHeight int
|
||||||
|
HasInventory bool // if true, item can store gems or runes
|
||||||
|
GemSockets int // number of gems to store
|
||||||
|
GemApplyType int // what kind of gem effect is applied
|
||||||
|
// 0 = weapon, 1= armor or helmet, 2 = shield
|
||||||
|
|
||||||
|
FlippyFile string // DC6 file animation to play when item drops on the ground
|
||||||
|
InventoryFile string // DC6 file used in your inventory
|
||||||
|
UniqueInventoryFile string // DC6 file used by the unique version of this item
|
||||||
|
SetInventoryFile string // DC6 file used by the set version of this item
|
||||||
|
|
||||||
|
// these represent how player animations and graphics change upon wearing this
|
||||||
|
// these come from ArmType.txt
|
||||||
|
AnimRightArm int
|
||||||
|
AnimLeftArm int
|
||||||
|
AnimTorso int
|
||||||
|
AnimLegs int
|
||||||
|
AnimRightShoulderPad int
|
||||||
|
AnimLeftShoulderPad int
|
||||||
|
|
||||||
|
Useable bool // can be used via right click if true
|
||||||
|
// game knows what to do if used by item code
|
||||||
|
Throwable bool
|
||||||
|
Stackable bool // can be stacked in inventory
|
||||||
|
MinStack int // min size of stack when item is spawned, used if stackable
|
||||||
|
MaxStack int // max size of stack when item is spawned
|
||||||
|
|
||||||
|
Type string // base type in ItemTypes.txt
|
||||||
|
Type2 string
|
||||||
|
|
||||||
|
DropSound string // sfx for dropping
|
||||||
|
DropSfxFrame int // what frame of drop animation the sfx triggers on
|
||||||
|
UseSound string // sfx for using
|
||||||
|
|
||||||
|
Unique bool // if true, only spawns as unique
|
||||||
|
Transparent bool // unused
|
||||||
|
TransTable int // unknown, related to blending mode?
|
||||||
|
Quivered bool // if true, requires ammo to use
|
||||||
|
LightRadius int // apparently unused
|
||||||
|
Belt bool // tells what kind of belt this item is
|
||||||
|
|
||||||
|
Quest int // indicates that this item belongs to a given quest?
|
||||||
|
|
||||||
|
MissileType int // missile gfx for throwing
|
||||||
|
DurabilityWarning int // controls what warning icon appears when durability is low
|
||||||
|
QuantityWarning int // controls at what quantity the low quantity warning appears
|
||||||
|
|
||||||
|
MinDamage int
|
||||||
|
MaxDamage int
|
||||||
|
StrengthBonus int
|
||||||
|
DexterityBonus int
|
||||||
|
// final mindam = min * str / strbonus + min * dex / dexbonus
|
||||||
|
// same for maxdam
|
||||||
|
|
||||||
|
GemOffset int // unknown
|
||||||
|
BitField1 int // 1 = leather item, 3 = metal
|
||||||
|
|
||||||
|
Vendors map[string]*ItemVendorParams // controls vendor settings
|
||||||
|
|
||||||
|
SourceArt string // unused?
|
||||||
|
GameArt string // unused?
|
||||||
|
ColorTransform int // colormap to use for player's gfx
|
||||||
|
InventoryColorTransform int // colormap to use for inventory's gfx
|
||||||
|
|
||||||
|
SkipName bool // if true, don't include the base name in the item description
|
||||||
|
NightmareUpgrade string // upgraded in higher difficulties
|
||||||
|
HellUpgrade string
|
||||||
|
|
||||||
|
Nameable bool // if true, item can be personalized
|
||||||
|
|
||||||
|
|
||||||
|
// weapon params
|
||||||
|
BarbOneOrTwoHanded bool // if true, barb can wield this in one or two hands
|
||||||
|
UsesTwoHands bool // if true, it's a 2handed weapon
|
||||||
|
Min2HandDamage int
|
||||||
|
Max2HandDamage int
|
||||||
|
MinMissileDamage int // ranged damage stats
|
||||||
|
MaxMissileDamage int
|
||||||
|
MissileSpeed int // unknown, affects movement speed of wielder during ranged attacks?
|
||||||
|
ExtraRange int // base range = 1, if this is non-zero add this to the range
|
||||||
|
// final mindam = min * str / strbonus + min * dex / dexbonus
|
||||||
|
// same for maxdam
|
||||||
|
RequiredDexterity int
|
||||||
|
|
||||||
|
WeaponClass string // what kind of attack does this weapon have (i.e. determines attack animations)
|
||||||
|
WeaponClass2Hand string // what kind of attack when wielded with two hands
|
||||||
|
HitClass string // determines sounds/graphic effects when attacking
|
||||||
|
SpawnStack int // unknown, something to do with stack size when spawned (sold maybe?)
|
||||||
|
|
||||||
|
SpecialFeature string // Just a comment
|
||||||
|
|
||||||
|
QuestDifficultyCheck bool // if true, item only works in the difficulty it was found in
|
||||||
|
|
||||||
|
PermStoreItem bool // if true, vendor will always sell this
|
||||||
|
|
||||||
|
// misc params
|
||||||
|
FlavorText string // unknown, probably just for reference
|
||||||
|
|
||||||
|
Transmogrify bool // if true, can be turned into another item via right click
|
||||||
|
TransmogCode string // the 3 char code representing the item this becomes via transmog
|
||||||
|
TransmogMin int // min amount of the transmog item to create
|
||||||
|
TransmogMax int // max ''
|
||||||
|
|
||||||
|
AutoBelt bool // if true, item is put into your belt when picked up
|
||||||
|
|
||||||
|
SpellIcon int // which icon to display when used? Is this always -1?
|
||||||
|
SpellType int // determines what kind of function is used when you use this item
|
||||||
|
OverlayState string // name of the overlay state to be applied upon use of this item
|
||||||
|
CureOverlayStates [2]string // name of the overlay states that are removed upon use of this item
|
||||||
|
EffectLength int // timer for timed usage effects
|
||||||
|
UsageStats [3]ItemUsageStat // stat boosts applied upon usage
|
||||||
|
|
||||||
|
SpellDescriptionType int // specifies how to format the usage description
|
||||||
|
// 0 = none, 1 = use desc string, 2 = use desc string + calc value
|
||||||
|
SpellDescriptionString string // points to a string containing the description
|
||||||
|
SpellDescriptionCalc d2common.CalcString // a calc string what value to display
|
||||||
|
|
||||||
|
BetterGem string // 3 char code pointing to the gem this upgrades to (non if not applicable)
|
||||||
|
|
||||||
|
Multibuy bool // if true, when you buy via right click + shift it will fill your belt automatically
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemUsageStat struct {
|
||||||
|
Stat string // name of the stat to add to
|
||||||
|
Calc d2common.CalcString // calc string representing the amount to add
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemVendorParams struct {
|
||||||
|
Min int // minimum of this item they can stock
|
||||||
|
Max int // max they can stock
|
||||||
|
MagicMin int
|
||||||
|
MagicMax int
|
||||||
|
MagicLevel uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Loading Functions
|
||||||
|
var CommonItems map[string]*ItemCommonRecord
|
||||||
|
|
||||||
|
func LoadCommonItems(fileProvider d2interface.FileProvider, filepath string, source d2enum.InventoryItemType) *map[string]*ItemCommonRecord {
|
||||||
|
if CommonItems == nil {
|
||||||
|
CommonItems = make(map[string]*ItemCommonRecord)
|
||||||
|
}
|
||||||
|
items := make(map[string]*ItemCommonRecord)
|
||||||
|
data := strings.Split(string(fileProvider.LoadFile(filepath)), "\r\n")
|
||||||
|
mapping := MapHeaders(data[0])
|
||||||
|
for lineno, line := range data {
|
||||||
|
if lineno == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rec := createCommonItemRecord(line, &mapping, source)
|
||||||
|
items[rec.Code] = &rec
|
||||||
|
CommonItems[rec.Code] = &rec
|
||||||
|
}
|
||||||
|
return &items
|
||||||
|
}
|
||||||
|
|
||||||
|
func createCommonItemRecord(line string, mapping *map[string]int, source d2enum.InventoryItemType) ItemCommonRecord {
|
||||||
|
r := strings.Split(line, "\t")
|
||||||
|
result := ItemCommonRecord{
|
||||||
|
Source: source,
|
||||||
|
|
||||||
|
Name: MapLoadString(&r, mapping, "name"),
|
||||||
|
|
||||||
|
Version: MapLoadInt(&r, mapping, "version"),
|
||||||
|
CompactSave: MapLoadBool(&r, mapping, "compactsave"),
|
||||||
|
Rarity: MapLoadInt(&r, mapping, "rarity"),
|
||||||
|
Spawnable: MapLoadBool(&r, mapping, "spawnable"),
|
||||||
|
|
||||||
|
MinAC: MapLoadInt(&r, mapping, "minac"),
|
||||||
|
MaxAC: MapLoadInt(&r, mapping, "maxac"),
|
||||||
|
Absorbs: MapLoadInt(&r, mapping, "absorbs"),
|
||||||
|
Speed: MapLoadInt(&r, mapping, "speed"),
|
||||||
|
RequiredStrength: MapLoadInt(&r, mapping, "reqstr"),
|
||||||
|
Block: MapLoadInt(&r, mapping, "block"),
|
||||||
|
Durability: MapLoadInt(&r, mapping, "durability"),
|
||||||
|
NoDurability: MapLoadBool(&r, mapping, "nodurability"),
|
||||||
|
|
||||||
|
Level: MapLoadInt(&r, mapping, "level"),
|
||||||
|
RequiredLevel: MapLoadInt(&r, mapping, "levelreq"),
|
||||||
|
Cost: MapLoadInt(&r, mapping, "cost"),
|
||||||
|
GambleCost: MapLoadInt(&r, mapping, "gamble cost"),
|
||||||
|
Code: MapLoadString(&r, mapping, "code"),
|
||||||
|
NameString: MapLoadString(&r, mapping, "namestr"),
|
||||||
|
MagicLevel: MapLoadInt(&r, mapping, "magic lvl"),
|
||||||
|
AutoPrefix: MapLoadInt(&r, mapping, "auto prefix"),
|
||||||
|
|
||||||
|
AlternateGfx: MapLoadString(&r, mapping, "alternategfx"),
|
||||||
|
OpenBetaGfx: MapLoadString(&r, mapping, "OpenBetaGfx"),
|
||||||
|
NormalCode: MapLoadString(&r, mapping, "normcode"),
|
||||||
|
UberCode: MapLoadString(&r, mapping, "ubercode"),
|
||||||
|
UltraCode: MapLoadString(&r, mapping, "ultracode"),
|
||||||
|
|
||||||
|
SpellOffset: MapLoadInt(&r, mapping, "spelloffset"),
|
||||||
|
|
||||||
|
Component: MapLoadInt(&r, mapping, "component"),
|
||||||
|
InventoryWidth: MapLoadInt(&r, mapping, "invwidth"),
|
||||||
|
InventoryHeight: MapLoadInt(&r, mapping, "invheight"),
|
||||||
|
HasInventory: MapLoadBool(&r, mapping, "hasinv"),
|
||||||
|
GemSockets: MapLoadInt(&r, mapping, "gemsockets"),
|
||||||
|
GemApplyType: MapLoadInt(&r, mapping, "gemapplytype"),
|
||||||
|
|
||||||
|
FlippyFile: MapLoadString(&r, mapping, "flippyfile"),
|
||||||
|
InventoryFile: MapLoadString(&r, mapping, "invfile"),
|
||||||
|
UniqueInventoryFile: MapLoadString(&r, mapping, "uniqueinvfile"),
|
||||||
|
SetInventoryFile: MapLoadString(&r, mapping, "setinvfile"),
|
||||||
|
|
||||||
|
AnimRightArm: MapLoadInt(&r, mapping, "rArm"),
|
||||||
|
AnimLeftArm: MapLoadInt(&r, mapping, "lArm"),
|
||||||
|
AnimTorso: MapLoadInt(&r, mapping, "Torso"),
|
||||||
|
AnimLegs: MapLoadInt(&r, mapping, "Legs"),
|
||||||
|
AnimRightShoulderPad: MapLoadInt(&r, mapping, "rSPad"),
|
||||||
|
AnimLeftShoulderPad: MapLoadInt(&r, mapping, "lSPad"),
|
||||||
|
|
||||||
|
Useable: MapLoadBool(&r, mapping, "useable"),
|
||||||
|
|
||||||
|
Throwable: MapLoadBool(&r, mapping, "throwable"),
|
||||||
|
Stackable: MapLoadBool(&r, mapping, "stackable"),
|
||||||
|
MinStack: MapLoadInt(&r, mapping, "minstack"),
|
||||||
|
MaxStack: MapLoadInt(&r, mapping, "maxstack"),
|
||||||
|
|
||||||
|
Type: MapLoadString(&r, mapping, "type"),
|
||||||
|
Type2: MapLoadString(&r, mapping, "type2"),
|
||||||
|
|
||||||
|
DropSound: MapLoadString(&r, mapping, "dropsound"),
|
||||||
|
DropSfxFrame: MapLoadInt(&r, mapping, "dropsfxframe"),
|
||||||
|
UseSound: MapLoadString(&r, mapping, "usesound"),
|
||||||
|
|
||||||
|
Unique: MapLoadBool(&r, mapping, "unique"),
|
||||||
|
Transparent: MapLoadBool(&r, mapping, "transparent"),
|
||||||
|
TransTable: MapLoadInt(&r, mapping, "transtbl"),
|
||||||
|
Quivered: MapLoadBool(&r, mapping, "quivered"),
|
||||||
|
LightRadius: MapLoadInt(&r, mapping, "lightradius"),
|
||||||
|
Belt: MapLoadBool(&r, mapping, "belt"),
|
||||||
|
|
||||||
|
Quest: MapLoadInt(&r, mapping, "quest"),
|
||||||
|
|
||||||
|
MissileType: MapLoadInt(&r, mapping, "missiletype"),
|
||||||
|
DurabilityWarning: MapLoadInt(&r, mapping, "durwarning"),
|
||||||
|
QuantityWarning: MapLoadInt(&r, mapping, "qntwarning"),
|
||||||
|
|
||||||
|
MinDamage: MapLoadInt(&r, mapping, "mindam"),
|
||||||
|
MaxDamage: MapLoadInt(&r, mapping, "maxdam"),
|
||||||
|
StrengthBonus: MapLoadInt(&r, mapping, "StrBonus"),
|
||||||
|
DexterityBonus: MapLoadInt(&r, mapping, "DexBonus"),
|
||||||
|
|
||||||
|
GemOffset: MapLoadInt(&r, mapping, "gemoffset"),
|
||||||
|
BitField1: MapLoadInt(&r, mapping, "bitfield1"),
|
||||||
|
|
||||||
|
Vendors: createItemVendorParams(&r, mapping),
|
||||||
|
|
||||||
|
SourceArt: MapLoadString(&r, mapping, "Source Art"),
|
||||||
|
GameArt: MapLoadString(&r, mapping, "Game Art"),
|
||||||
|
ColorTransform: MapLoadInt(&r, mapping, "Transform"),
|
||||||
|
InventoryColorTransform: MapLoadInt(&r, mapping, "InvTrans"),
|
||||||
|
|
||||||
|
SkipName: MapLoadBool(&r, mapping, "SkipName"),
|
||||||
|
NightmareUpgrade: MapLoadString(&r, mapping, "NightmareUpgrade"),
|
||||||
|
HellUpgrade: MapLoadString(&r, mapping, "HellUpgrade"),
|
||||||
|
|
||||||
|
Nameable: MapLoadBool(&r, mapping, "Nameable"),
|
||||||
|
|
||||||
|
// weapon params
|
||||||
|
BarbOneOrTwoHanded: MapLoadBool(&r, mapping, "1or2handed"),
|
||||||
|
UsesTwoHands: MapLoadBool(&r, mapping, "2handed"),
|
||||||
|
Min2HandDamage: MapLoadInt(&r, mapping, "2handmindam"),
|
||||||
|
Max2HandDamage: MapLoadInt(&r, mapping, "2handmaxdam"),
|
||||||
|
MinMissileDamage: MapLoadInt(&r, mapping, "minmisdam"),
|
||||||
|
MaxMissileDamage: MapLoadInt(&r, mapping, "maxmisdam"),
|
||||||
|
MissileSpeed: MapLoadInt(&r, mapping, "misspeed"),
|
||||||
|
ExtraRange: MapLoadInt(&r, mapping, "rangeadder"),
|
||||||
|
|
||||||
|
RequiredDexterity: MapLoadInt(&r, mapping, "reqdex"),
|
||||||
|
|
||||||
|
WeaponClass: MapLoadString(&r, mapping, "wclass"),
|
||||||
|
WeaponClass2Hand: MapLoadString(&r, mapping, "2handedwclass"),
|
||||||
|
|
||||||
|
HitClass: MapLoadString(&r, mapping, "hit class"),
|
||||||
|
SpawnStack: MapLoadInt(&r, mapping, "spawnstack"),
|
||||||
|
|
||||||
|
SpecialFeature: MapLoadString(&r, mapping, "special"),
|
||||||
|
|
||||||
|
QuestDifficultyCheck: MapLoadBool(&r, mapping, "questdiffcheck"),
|
||||||
|
|
||||||
|
PermStoreItem: MapLoadBool(&r, mapping, "PermStoreItem"),
|
||||||
|
|
||||||
|
// misc params
|
||||||
|
FlavorText: MapLoadString(&r, mapping, "szFlavorText"),
|
||||||
|
|
||||||
|
Transmogrify: MapLoadBool(&r, mapping, "Transmogrify"),
|
||||||
|
TransmogCode: MapLoadString(&r, mapping, "TMogType"),
|
||||||
|
TransmogMin: MapLoadInt(&r, mapping, "TMogMin"),
|
||||||
|
TransmogMax: MapLoadInt(&r, mapping, "TMogMax"),
|
||||||
|
|
||||||
|
AutoBelt: MapLoadBool(&r, mapping, "autobelt"),
|
||||||
|
|
||||||
|
SpellIcon: MapLoadInt(&r, mapping, "spellicon"),
|
||||||
|
SpellType: MapLoadInt(&r, mapping, "pSpell"),
|
||||||
|
OverlayState: MapLoadString(&r, mapping, "state"),
|
||||||
|
CureOverlayStates: [2]string{
|
||||||
|
MapLoadString(&r, mapping, "cstate1"),
|
||||||
|
MapLoadString(&r, mapping, "cstate2"),
|
||||||
|
},
|
||||||
|
EffectLength: MapLoadInt(&r, mapping, "len"),
|
||||||
|
UsageStats: createItemUsageStats(&r, mapping),
|
||||||
|
|
||||||
|
SpellDescriptionType: MapLoadInt(&r, mapping, "spelldesc"),
|
||||||
|
// 0 = none, 1 = use desc string, 2 = use desc string + calc value
|
||||||
|
SpellDescriptionString: MapLoadString(&r, mapping, "spelldescstr"),
|
||||||
|
SpellDescriptionCalc: d2common.CalcString(MapLoadString(&r, mapping, "spelldesccalc")),
|
||||||
|
|
||||||
|
BetterGem: MapLoadString(&r, mapping, "BetterGem"),
|
||||||
|
|
||||||
|
Multibuy: MapLoadBool(&r, mapping, "multibuy"),
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func createItemVendorParams(r *[]string, mapping *map[string]int) map[string]*ItemVendorParams {
|
||||||
|
vs := make([]string, 17)
|
||||||
|
vs[0] = "Charsi"
|
||||||
|
vs[1] = "Gheed"
|
||||||
|
vs[2] = "Akara"
|
||||||
|
vs[3] = "Fara"
|
||||||
|
vs[4] = "Lysander"
|
||||||
|
vs[5] = "Drognan"
|
||||||
|
vs[6] = "Hralti"
|
||||||
|
vs[7] = "Alkor"
|
||||||
|
vs[8] = "Ormus"
|
||||||
|
vs[9] = "Elzix"
|
||||||
|
vs[10] = "Asheara"
|
||||||
|
vs[11] = "Cain"
|
||||||
|
vs[12] = "Halbu"
|
||||||
|
vs[13] = "Jamella"
|
||||||
|
vs[14] = "Larzuk"
|
||||||
|
vs[15] = "Malah"
|
||||||
|
vs[16] = "Drehya"
|
||||||
|
|
||||||
|
result := make(map[string]*ItemVendorParams)
|
||||||
|
|
||||||
|
for _, name := range vs {
|
||||||
|
wvp := ItemVendorParams{
|
||||||
|
Min: MapLoadInt(r, mapping, name + "Min"),
|
||||||
|
Max: MapLoadInt(r, mapping, name + "Max"),
|
||||||
|
MagicMin: MapLoadInt(r, mapping, name + "MagicMin"),
|
||||||
|
MagicMax: MapLoadInt(r, mapping, name + "MagicMax"),
|
||||||
|
MagicLevel: MapLoadUint8(r, mapping, name + "MagicLvl"),
|
||||||
|
}
|
||||||
|
result[name] = &wvp
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func createItemUsageStats(r *[]string, mapping *map[string]int) [3]ItemUsageStat {
|
||||||
|
result := [3]ItemUsageStat{}
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
result[i].Stat = MapLoadString(r, mapping, "stat" + strconv.Itoa(i))
|
||||||
|
result[i].Calc = d2common.CalcString(MapLoadString(r, mapping, "calc" + strconv.Itoa(i)))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
43
d2data/d2datadict/map_helper.go
Normal file
43
d2data/d2datadict/map_helper.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package d2datadict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapLoadInt(r *[]string, mapping *map[string]int, field string) int {
|
||||||
|
index, ok := (*mapping)[field]
|
||||||
|
if ok {
|
||||||
|
return dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty((*r)[index])))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapLoadString(r *[]string, mapping *map[string]int, field string) string {
|
||||||
|
index, ok := (*mapping)[field]
|
||||||
|
if ok {
|
||||||
|
return dh.AsterToEmpty((*r)[index])
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapLoadBool(r *[]string, mapping *map[string]int, field string) bool {
|
||||||
|
return MapLoadInt(r, mapping, field) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapLoadUint8(r *[]string, mapping *map[string]int, field string) uint8 {
|
||||||
|
index, ok := (*mapping)[field]
|
||||||
|
if ok {
|
||||||
|
return dh.StringToUint8(dh.EmptyToZero(dh.AsterToEmpty((*r)[index])))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
18
d2data/d2datadict/misc.go
Normal file
18
d2data/d2datadict/misc.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package d2datadict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MiscItems map[string]*ItemCommonRecord
|
||||||
|
|
||||||
|
func LoadMiscItems(fileProvider d2interface.FileProvider) {
|
||||||
|
MiscItems = *LoadCommonItems(fileProvider, d2resource.Misc, d2enum.InventoryItemTypeItem)
|
||||||
|
log.Printf("Loaded %d misc items", len(MiscItems))
|
||||||
|
}
|
@ -4,6 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
@ -17,7 +19,7 @@ type MissileCalcParam struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MissileCalc struct {
|
type MissileCalc struct {
|
||||||
Calc string
|
Calc d2common.CalcString
|
||||||
Desc string
|
Desc string
|
||||||
Params []MissileCalcParam
|
Params []MissileCalcParam
|
||||||
}
|
}
|
||||||
@ -64,7 +66,7 @@ type MissileDamage struct {
|
|||||||
MinLevelDamage [5]int // additional damage per missile level
|
MinLevelDamage [5]int // additional damage per missile level
|
||||||
// [0]: lvs 2-8, [1]: lvs 9-16, [2]: lvs 17-22, [3]: lvs 23-28, [4]: lv 29+
|
// [0]: lvs 2-8, [1]: lvs 9-16, [2]: lvs 17-22, [3]: lvs 23-28, [4]: lv 29+
|
||||||
MaxLevelDamage [5]int // see above
|
MaxLevelDamage [5]int // see above
|
||||||
DamageSynergyPerCalc string // works like synergy in skills.txt, not clear
|
DamageSynergyPerCalc d2common.CalcString // works like synergy in skills.txt, not clear
|
||||||
}
|
}
|
||||||
|
|
||||||
type MissileElementalDamage struct {
|
type MissileElementalDamage struct {
|
||||||
@ -318,7 +320,7 @@ func loadMissileCalcParam(r *[]string, inc func() int) MissileCalcParam {
|
|||||||
|
|
||||||
func loadMissileCalc(r *[]string, inc func() int, params int) MissileCalc {
|
func loadMissileCalc(r *[]string, inc func() int, params int) MissileCalc {
|
||||||
result := MissileCalc{
|
result := MissileCalc{
|
||||||
Calc: (*r)[inc()],
|
Calc: d2common.CalcString((*r)[inc()]),
|
||||||
Desc: (*r)[inc()],
|
Desc: (*r)[inc()],
|
||||||
}
|
}
|
||||||
result.Params = make([]MissileCalcParam, params)
|
result.Params = make([]MissileCalcParam, params)
|
||||||
@ -389,7 +391,7 @@ func loadMissileDamage(r *[]string, inc func() int) MissileDamage {
|
|||||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||||
},
|
},
|
||||||
DamageSynergyPerCalc: (*r)[inc()],
|
DamageSynergyPerCalc: d2common.CalcString((*r)[inc()]),
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
@ -47,7 +49,7 @@ type UniqueItemRecord struct {
|
|||||||
|
|
||||||
type UniqueItemProperty struct {
|
type UniqueItemProperty struct {
|
||||||
Property string
|
Property string
|
||||||
Parameter string // depending on the property, this may be an int (usually), or a string
|
Parameter d2common.CalcString // depending on the property, this may be an int (usually), or a string
|
||||||
Min int
|
Min int
|
||||||
Max int
|
Max int
|
||||||
}
|
}
|
||||||
@ -109,7 +111,7 @@ func createUniqueItemRecord(r []string) UniqueItemRecord {
|
|||||||
func createUniqueItemProperty(r *[]string, inc func() int) UniqueItemProperty {
|
func createUniqueItemProperty(r *[]string, inc func() int) UniqueItemProperty {
|
||||||
result := UniqueItemProperty{
|
result := UniqueItemProperty{
|
||||||
Property: (*r)[inc()],
|
Property: (*r)[inc()],
|
||||||
Parameter: (*r)[inc()],
|
Parameter: d2common.CalcString((*r)[inc()]),
|
||||||
Min: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
Min: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||||
Max: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
Max: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||||
}
|
}
|
||||||
|
@ -2,288 +2,17 @@ package d2datadict
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
|
||||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type WeaponRecord struct {
|
var Weapons map[string]*ItemCommonRecord
|
||||||
Name string
|
|
||||||
|
|
||||||
Type string // base type in ItemTypes.txt
|
|
||||||
Type2 string
|
|
||||||
Code string // identifies the item
|
|
||||||
AlternateGfx string // code of the DCC used when equipped
|
|
||||||
NameString string // seems to be identical to code?
|
|
||||||
Version int // 0 = classic, 100 = expansion
|
|
||||||
CompactSave bool // if true, doesn't store any stats upon saving
|
|
||||||
Rarity int // higher, the rarer
|
|
||||||
Spawnable bool // if 0, cannot spawn in shops
|
|
||||||
|
|
||||||
MinDamage int
|
|
||||||
MaxDamage int
|
|
||||||
BarbOneOrTwoHanded bool // if true, barb can wield this in one or two hands
|
|
||||||
UsesTwoHands bool // if true, it's a 2handed weapon
|
|
||||||
Min2HandDamage int
|
|
||||||
Max2HandDamage int
|
|
||||||
MinMissileDamage int // ranged damage stats
|
|
||||||
MaxMissileDamage int
|
|
||||||
MissileSpeed int // unknown, affects movement speed of wielder during ranged attacks?
|
|
||||||
ExtraRange int // base range = 1, if this is non-zero add this to the range
|
|
||||||
Speed int // affects movement speed of wielder, >0 = you move slower, <0 = you move faster
|
|
||||||
StrengthBonus int
|
|
||||||
DexterityBonus int
|
|
||||||
// final mindam = min * str / strbonus + min * dex / dexbonus
|
|
||||||
// same for maxdam
|
|
||||||
RequiredStrength int
|
|
||||||
RequiredDexterity int
|
|
||||||
Durability int // base durability 0-255
|
|
||||||
NoDurability bool // if true, item has no durability
|
|
||||||
|
|
||||||
Level int // base item level (controls monster drops, for instance a lv20 monster cannot drop a lv30 item)
|
|
||||||
RequiredLevel int // required level to wield
|
|
||||||
Cost int // base cost
|
|
||||||
GambleCost int // for reference only, not used
|
|
||||||
MagicLevel int // additional magic level (for gambling?)
|
|
||||||
AutoPrefix int // prefix automatically assigned to this item on spawn, maps to group column of Automagic.txt
|
|
||||||
OpenBetaGfx string // unknown
|
|
||||||
NormalCode string
|
|
||||||
UberCode string
|
|
||||||
UltraCode string
|
|
||||||
|
|
||||||
WeaponClass string // what kind of attack does this weapon have (i.e. determines attack animations)
|
|
||||||
WeaponClass2Hand string // what kind of attack when wielded with two hands
|
|
||||||
Component int // corresponds to Composit.txt, player animation layer used by this
|
|
||||||
HitClass string // determines sounds/graphic effects when attacking
|
|
||||||
InventoryWidth int
|
|
||||||
InventoryHeight int
|
|
||||||
Stackable bool // can be stacked in inventory
|
|
||||||
MinStack int // min size of stack when item is spawned, used if stackable
|
|
||||||
MaxStack int // max size of stack when item is spawned
|
|
||||||
SpawnStack int // unknown, something to do with stack size when spawned (sold maybe?)
|
|
||||||
|
|
||||||
FlippyFile string // DC6 file animation to play when item drops on the ground
|
|
||||||
InventoryFile string // DC6 file used in your inventory
|
|
||||||
UniqueInventoryFile string // DC6 file used by the unique version of this item
|
|
||||||
SetInventoryFile string // DC6 file used by the set version of this item
|
|
||||||
|
|
||||||
HasInventory bool // if true, item can store gems or runes
|
|
||||||
GemSockets int // number of gems to store
|
|
||||||
GemApplyType int // what kind of gem effect is applied
|
|
||||||
// 0 = weapon, 1= armor or helmet, 2 = shield
|
|
||||||
|
|
||||||
SpecialFeature string // Just a comment
|
|
||||||
|
|
||||||
Useable bool // can be used via right click if true
|
|
||||||
// game knows what to do if used by item code
|
|
||||||
DropSound string // sfx for dropping
|
|
||||||
DropSfxFrame int // what frame of drop animation the sfx triggers on
|
|
||||||
UseSound string // sfx for using
|
|
||||||
|
|
||||||
Unique bool // if true, only spawns as unique
|
|
||||||
Transparent bool // unused
|
|
||||||
TransTable int // unknown, related to blending mode?
|
|
||||||
Quivered bool // if true, requires ammo to use
|
|
||||||
LightRadius int // apparently unused
|
|
||||||
Belt bool // seems to be unused? supposed to be whether this can go in your quick access belt
|
|
||||||
|
|
||||||
Quest int // indicates that this item belongs to a given quest?
|
|
||||||
QuestDifficultyCheck bool // if true, item only works in the difficulty it was found in
|
|
||||||
|
|
||||||
MissileType int // missile gfx for throwing
|
|
||||||
DurabilityWarning int // controls what warning icon appears when durability is low
|
|
||||||
QuantityWarning int // controls at what quantity the low quantity warning appears
|
|
||||||
GemOffset int // unknown
|
|
||||||
BitField1 int // 1 = leather item, 3 = metal
|
|
||||||
|
|
||||||
Vendors map[string]*ItemVendorParams // controls vendor settings
|
|
||||||
|
|
||||||
SourceArt string // unused?
|
|
||||||
GameArt string // unused?
|
|
||||||
ColorTransform int // colormap to use for player's gfx
|
|
||||||
InventoryColorTransform int // colormap to use for inventory's gfx
|
|
||||||
|
|
||||||
SkipName bool // if true, don't include the base name in the item description
|
|
||||||
NightmareUpgrade string // upgraded in higher difficulties
|
|
||||||
HellUpgrade string
|
|
||||||
|
|
||||||
Nameable bool // if true, item can be personalized
|
|
||||||
PermStoreItem bool // if true, vendor will always sell this
|
|
||||||
}
|
|
||||||
|
|
||||||
type ItemVendorParams struct {
|
|
||||||
Min int // minimum of this item they can stock
|
|
||||||
Max int // max they can stock
|
|
||||||
MagicMin int
|
|
||||||
MagicMax int
|
|
||||||
MagicLevel uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
func createWeaponRecord(line string) WeaponRecord {
|
|
||||||
r := strings.Split(line, "\t")
|
|
||||||
i := -1
|
|
||||||
inc := func() int {
|
|
||||||
i++
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
result := WeaponRecord{
|
|
||||||
Name: r[inc()],
|
|
||||||
|
|
||||||
Type: r[inc()],
|
|
||||||
Type2: r[inc()],
|
|
||||||
Code: r[inc()],
|
|
||||||
AlternateGfx: r[inc()],
|
|
||||||
NameString: r[inc()],
|
|
||||||
Version: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
CompactSave: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
Rarity: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Spawnable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
|
|
||||||
MinDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MaxDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
BarbOneOrTwoHanded: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
UsesTwoHands: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
Min2HandDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Max2HandDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MinMissileDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MaxMissileDamage: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MissileSpeed: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
ExtraRange: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Speed: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
StrengthBonus: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
DexterityBonus: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
|
|
||||||
RequiredStrength: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
RequiredDexterity: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Durability: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
NoDurability: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
|
|
||||||
Level: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
RequiredLevel: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Cost: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
GambleCost: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MagicLevel: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
AutoPrefix: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
OpenBetaGfx: r[inc()],
|
|
||||||
NormalCode: r[inc()],
|
|
||||||
UberCode: r[inc()],
|
|
||||||
UltraCode: r[inc()],
|
|
||||||
|
|
||||||
WeaponClass: r[inc()],
|
|
||||||
WeaponClass2Hand: r[inc()],
|
|
||||||
Component: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
HitClass: r[inc()],
|
|
||||||
InventoryWidth: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
InventoryHeight: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Stackable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
MinStack: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
MaxStack: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
SpawnStack: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
|
|
||||||
FlippyFile: r[inc()],
|
|
||||||
InventoryFile: r[inc()],
|
|
||||||
UniqueInventoryFile: r[inc()],
|
|
||||||
SetInventoryFile: r[inc()],
|
|
||||||
|
|
||||||
HasInventory: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
GemSockets: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
GemApplyType: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
|
|
||||||
SpecialFeature: r[inc()],
|
|
||||||
|
|
||||||
Useable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
|
|
||||||
DropSound: r[inc()],
|
|
||||||
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
UseSound: r[inc()],
|
|
||||||
|
|
||||||
Unique: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
Transparent: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
TransTable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Quivered: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
LightRadius: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
Belt: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
|
|
||||||
Quest: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
QuestDifficultyCheck: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
|
|
||||||
MissileType: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
DurabilityWarning: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
QuantityWarning: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
GemOffset: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
BitField1: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
|
|
||||||
Vendors: createWeaponVendorParams(&r, inc),
|
|
||||||
|
|
||||||
SourceArt: r[inc()],
|
|
||||||
GameArt: r[inc()],
|
|
||||||
ColorTransform: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
InventoryColorTransform: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
|
||||||
|
|
||||||
SkipName: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
NightmareUpgrade: r[inc()],
|
|
||||||
HellUpgrade: r[inc()],
|
|
||||||
|
|
||||||
Nameable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
PermStoreItem: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func createWeaponVendorParams(r *[]string, inc func() int) map[string]*ItemVendorParams {
|
|
||||||
vs := make([]string, 17)
|
|
||||||
vs[0] = "Charsi"
|
|
||||||
vs[1] = "Gheed"
|
|
||||||
vs[2] = "Akara"
|
|
||||||
vs[3] = "Fara"
|
|
||||||
vs[4] = "Lysander"
|
|
||||||
vs[5] = "Drognan"
|
|
||||||
vs[6] = "Hralti"
|
|
||||||
vs[7] = "Alkor"
|
|
||||||
vs[8] = "Ormus"
|
|
||||||
vs[9] = "Elzix"
|
|
||||||
vs[10] = "Asheara"
|
|
||||||
vs[11] = "Cain"
|
|
||||||
vs[12] = "Halbu"
|
|
||||||
vs[13] = "Jamella"
|
|
||||||
vs[14] = "Larzuk"
|
|
||||||
vs[15] = "Drehya"
|
|
||||||
vs[16] = "Malah"
|
|
||||||
|
|
||||||
return CreateItemVendorParams(r, inc, vs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateItemVendorParams(r *[]string, inc func() int, vs []string) map[string]*ItemVendorParams {
|
|
||||||
result := make(map[string]*ItemVendorParams)
|
|
||||||
|
|
||||||
for _, name := range vs {
|
|
||||||
wvp := ItemVendorParams{
|
|
||||||
Min: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
|
||||||
Max: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
|
||||||
MagicMin: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
|
||||||
MagicMax: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
|
||||||
MagicLevel: dh.StringToUint8(dh.EmptyToZero((*r)[inc()])),
|
|
||||||
}
|
|
||||||
result[name] = &wvp
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
var Weapons map[string]*WeaponRecord
|
|
||||||
|
|
||||||
func LoadWeapons(fileProvider d2interface.FileProvider) {
|
func LoadWeapons(fileProvider d2interface.FileProvider) {
|
||||||
Weapons = make(map[string]*WeaponRecord)
|
Weapons = *LoadCommonItems(fileProvider, d2resource.Weapons, d2enum.InventoryItemTypeWeapon)
|
||||||
data := strings.Split(string(fileProvider.LoadFile(d2resource.Weapons)), "\r\n")[1:]
|
|
||||||
for _, line := range data {
|
|
||||||
if len(line) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rec := createWeaponRecord(line)
|
|
||||||
Weapons[rec.Code] = &rec
|
|
||||||
}
|
|
||||||
log.Printf("Loaded %d weapons", len(Weapons))
|
log.Printf("Loaded %d weapons", len(Weapons))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user