1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-07 10:47:19 -05:00
OpenDiablo2/d2data/d2datadict/armor.go

283 lines
9.6 KiB
Go
Raw Normal View History

2019-11-10 08:51:02 -05:00
package d2datadict
2019-11-07 20:51:15 -05:00
import (
"log"
"strings"
2019-11-10 08:51:02 -05:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
2019-11-10 03:36:53 -05:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
2019-11-07 20:51:15 -05:00
)
type ArmorRecord struct {
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()],
2019-11-10 03:36:53 -05:00
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()])),
2019-11-07 20:51:15 -05:00
Code: r[inc()],
NameString: r[inc()],
2019-11-10 03:36:53 -05:00
MagicLevel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
AutoPrefix: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
AlternateGfx: r[inc()],
OpenBetaGfx: r[inc()],
NormalCode: r[inc()],
UberCode: r[inc()],
UltraCode: r[inc()],
2019-11-10 03:36:53 -05:00
SpellOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
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()])),
2019-11-07 20:51:15 -05:00
FlippyFile: r[inc()],
InventoryFile: r[inc()],
UniqueInventoryFile: r[inc()],
SetInventoryFile: r[inc()],
2019-11-10 03:36:53 -05:00
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()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
Useable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
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()])),
2019-11-07 20:51:15 -05:00
Type: r[inc()],
Type2: r[inc()],
DropSound: r[inc()],
2019-11-10 03:36:53 -05:00
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
UseSound: r[inc()],
2019-11-10 03:36:53 -05:00
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,
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
Quest: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
MissileType: dh.StringToInt(dh.EmptyToZero(r[inc()])),
DurabilityWarning: dh.StringToInt(dh.EmptyToZero(r[inc()])),
QuantityWarning: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
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()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
GemOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
BitField1: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
Vendors: createArmorVendorParams(&r, inc),
SourceArt: r[inc()],
GameArt: r[inc()],
2019-11-10 03:36:53 -05:00
ColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
InventoryColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
SkipName: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
2019-11-07 20:51:15 -05:00
NightmareUpgrade: r[inc()],
HellUpgrade: r[inc()],
2019-11-10 03:36:53 -05:00
UnusedMinDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
UnusedMaxDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
2019-11-07 20:51:15 -05:00
2019-11-10 03:36:53 -05:00
Nameable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
2019-11-07 20:51:15 -05:00
}
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
2019-11-10 03:36:53 -05:00
func LoadArmors(fileProvider d2interface.FileProvider) {
2019-11-07 20:51:15 -05:00
Armors = make(map[string]*ArmorRecord)
2019-11-10 08:51:02 -05:00
data := strings.Split(string(fileProvider.LoadFile(d2resource.Armor)), "\r\n")[1:]
2019-11-07 20:51:15 -05:00
for _, line := range data {
if len(line) == 0 {
continue
}
rec := createArmorRecord(line)
Armors[rec.Code] = &rec
}
log.Printf("Loaded %d armors", len(Armors))
}