2019-11-06 22:12:15 -05:00
|
|
|
package common
|
2019-11-03 11:04:58 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"strings"
|
|
|
|
|
2019-11-06 22:12:15 -05:00
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
2019-11-03 11:04:58 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// An ObjectRecord represents the settings for one type of object from objects.txt
|
|
|
|
type ObjectRecord struct {
|
2019-11-05 20:46:52 -05:00
|
|
|
Name string
|
2019-11-03 11:04:58 -05:00
|
|
|
Description string
|
2019-11-05 20:46:52 -05:00
|
|
|
Id int
|
|
|
|
Token string // refers to what graphics this object uses
|
2019-11-03 11:04:58 -05:00
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
SpawnMax int // unused?
|
|
|
|
Selectable [8]bool // is this mode selectable
|
|
|
|
TrapProbability int // unused
|
2019-11-03 11:04:58 -05:00
|
|
|
|
|
|
|
SizeX int
|
|
|
|
SizeY int
|
|
|
|
|
|
|
|
NTgtFX int // unknown
|
|
|
|
NTgtFY int // unknown
|
|
|
|
NTgtBX int // unknown
|
|
|
|
NTgtBY int // unknown
|
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
FrameCount [8]int // how many frames does this mode have, 0 = skip
|
|
|
|
FrameDelta [8]int // what rate is the animation played at (256 = 100% speed)
|
2019-11-03 11:04:58 -05:00
|
|
|
CycleAnimation [8]bool // probably whether animation loops
|
2019-11-05 20:46:52 -05:00
|
|
|
LightDiameter [8]int
|
|
|
|
BlocksLight [8]bool
|
|
|
|
HasCollision [8]bool
|
|
|
|
IsAttackable bool // do we kick it when interacting
|
|
|
|
StartFrame [8]int
|
|
|
|
|
|
|
|
EnvEffect bool // unknown
|
|
|
|
IsDoor bool
|
2019-11-03 11:04:58 -05:00
|
|
|
BlockVisibility bool // only works with IsDoor
|
2019-11-05 20:46:52 -05:00
|
|
|
Orientation int // unknown (1=sw, 2=nw, 3=se, 4=ne)
|
|
|
|
Trans int // controls palette mapping
|
2019-11-03 11:04:58 -05:00
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
OrderFlag [8]int // 0 = object, 1 = floor, 2 = wall
|
|
|
|
PreOperate bool // unknown
|
2019-11-03 11:04:58 -05:00
|
|
|
HasAnimationMode [8]bool // 'Mode' in source, true if this mode is used
|
|
|
|
|
|
|
|
XOffset int // in pixels offset
|
|
|
|
YOffset int
|
2019-11-05 20:46:52 -05:00
|
|
|
Draw bool // if false, object isn't drawn (shadow is still drawn and player can still select though)
|
2019-11-03 11:04:58 -05:00
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
LightRed byte // if lightdiameter is set, rgb of the light
|
2019-11-03 11:04:58 -05:00
|
|
|
LightGreen byte
|
2019-11-05 20:46:52 -05:00
|
|
|
LightBlue byte
|
2019-11-03 11:04:58 -05:00
|
|
|
|
|
|
|
SelHD bool // whether these DCC components are selectable
|
|
|
|
SelTR bool
|
|
|
|
SelLG bool
|
|
|
|
SelRA bool
|
|
|
|
SelLA bool
|
|
|
|
SelRH bool
|
|
|
|
SelLH bool
|
|
|
|
SelSH bool
|
2019-11-05 20:46:52 -05:00
|
|
|
SelS [8]bool
|
2019-11-03 11:04:58 -05:00
|
|
|
|
|
|
|
TotalPieces int // selectable DCC components count
|
2019-11-05 20:46:52 -05:00
|
|
|
SubClass int // subclass of object:
|
2019-11-03 11:04:58 -05:00
|
|
|
// 1 = shrine
|
|
|
|
// 2 = obelisk
|
|
|
|
// 4 = portal
|
|
|
|
// 8 = container
|
|
|
|
// 16 = arcane sanctuary gateway
|
|
|
|
// 32 = well
|
|
|
|
// 64 = waypoint
|
|
|
|
// 128 = secret jails door
|
|
|
|
|
|
|
|
XSpace int // unknown
|
|
|
|
YSpace int
|
|
|
|
|
|
|
|
NameOffset int // pixels to offset the name from the animation pivot
|
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
MonsterOk bool // unknown
|
|
|
|
OperateRange int // distance object can be used from, might be unused
|
|
|
|
ShrineFunction int // unused
|
|
|
|
Restore bool // if true, object is stored in memory and will be retained if you leave and re-enter the area
|
|
|
|
|
|
|
|
Parm [8]int // unknown
|
|
|
|
Act int // what acts this object can appear in (15 = all three)
|
|
|
|
Lockable bool
|
|
|
|
Gore bool // unknown, something with corpses
|
|
|
|
Sync bool // unknown
|
|
|
|
Flicker bool // light flickers if true
|
|
|
|
Damage int // amount of damage done by this (used depending on operatefn)
|
|
|
|
Beta bool // if true, appeared in the beta?
|
|
|
|
Overlay bool // unknown
|
2019-11-03 11:04:58 -05:00
|
|
|
CollisionSubst bool // unknown, controls some kind of special collision checking?
|
|
|
|
|
2019-11-05 20:46:52 -05:00
|
|
|
Left int // unknown, clickable bounding box?
|
|
|
|
Top int
|
|
|
|
Width int
|
2019-11-03 11:04:58 -05:00
|
|
|
Height int
|
|
|
|
|
|
|
|
OperateFn int // what function is called when the player clicks on the object
|
|
|
|
// (todo: we should enumerate all the functions somewhere, but probably not here
|
|
|
|
// b/c it's a very long list)
|
|
|
|
PopulateFn int // what function is used to spawn this object?
|
|
|
|
// (see above todo)
|
|
|
|
InitFn int // what function is run when the object is initialized?
|
|
|
|
// (see above todo)
|
|
|
|
ClientFn int // controls special audio-visual functions
|
|
|
|
// (see above todo)
|
|
|
|
|
|
|
|
RestoreVirgins bool // if true, only restores unused objects (see Restore)
|
2019-11-05 20:46:52 -05:00
|
|
|
BlockMissile bool // if true, missiles collide with this
|
|
|
|
DrawUnder bool // if true, drawn as a floor tile is
|
|
|
|
OpenWarp bool // needs clarification, controls whether highlighting shows
|
2019-11-03 11:04:58 -05:00
|
|
|
// 'To ...' or 'trap door' when highlighting, not sure which is T/F
|
|
|
|
AutoMap int // controls how this object appears on the map
|
|
|
|
// 0 = it doesn't, rest of modes need to be analyzed
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateObjectRecord parses a row from objects.txt into an object record
|
2019-11-03 22:03:22 -05:00
|
|
|
func createObjectRecord(props []string) ObjectRecord {
|
2019-11-03 11:04:58 -05:00
|
|
|
i := -1
|
|
|
|
inc := func() int {
|
|
|
|
i++
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
result := ObjectRecord{
|
2019-11-05 20:46:52 -05:00
|
|
|
Name: props[inc()],
|
2019-11-03 11:04:58 -05:00
|
|
|
Description: props[inc()],
|
2019-11-05 20:46:52 -05:00
|
|
|
Id: StringToInt(props[inc()]),
|
|
|
|
Token: props[inc()],
|
|
|
|
|
|
|
|
SpawnMax: StringToInt(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
Selectable: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
TrapProbability: StringToInt(props[inc()]),
|
|
|
|
|
2019-11-03 11:04:58 -05:00
|
|
|
SizeX: StringToInt(props[inc()]),
|
|
|
|
SizeY: StringToInt(props[inc()]),
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
NTgtFX: StringToInt(props[inc()]),
|
|
|
|
NTgtFY: StringToInt(props[inc()]),
|
|
|
|
NTgtBX: StringToInt(props[inc()]),
|
|
|
|
NTgtBY: StringToInt(props[inc()]),
|
|
|
|
|
2019-11-03 11:04:58 -05:00
|
|
|
FrameCount: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
|
|
|
FrameDelta: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
|
|
|
CycleAnimation: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
|
|
|
LightDiameter: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
|
|
|
BlocksLight: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
|
|
|
HasCollision: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
IsAttackable: StringToUint8(props[inc()]) == 1,
|
2019-11-03 11:04:58 -05:00
|
|
|
StartFrame: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
EnvEffect: StringToUint8(props[inc()]) == 1,
|
|
|
|
IsDoor: StringToUint8(props[inc()]) == 1,
|
|
|
|
BlockVisibility: StringToUint8(props[inc()]) == 1,
|
|
|
|
Orientation: StringToInt(props[inc()]),
|
|
|
|
Trans: StringToInt(props[inc()]),
|
|
|
|
|
2019-11-03 11:04:58 -05:00
|
|
|
OrderFlag: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
PreOperate: StringToUint8(props[inc()]) == 1,
|
2019-11-03 11:04:58 -05:00
|
|
|
HasAnimationMode: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
XOffset: StringToInt(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
YOffset: StringToInt(props[inc()]),
|
2019-11-05 20:46:52 -05:00
|
|
|
Draw: StringToUint8(props[inc()]) == 1,
|
|
|
|
|
|
|
|
LightRed: StringToUint8(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
LightGreen: StringToUint8(props[inc()]),
|
2019-11-05 20:46:52 -05:00
|
|
|
LightBlue: StringToUint8(props[inc()]),
|
|
|
|
|
|
|
|
SelHD: StringToUint8(props[inc()]) == 1,
|
2019-11-03 11:04:58 -05:00
|
|
|
SelTR: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelLG: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelRA: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelLA: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelRH: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelLH: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelSH: StringToUint8(props[inc()]) == 1,
|
|
|
|
SelS: [8]bool{
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
StringToUint8(props[inc()]) == 1,
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
TotalPieces: StringToInt(props[inc()]),
|
|
|
|
SubClass: StringToInt(props[inc()]),
|
|
|
|
|
|
|
|
XSpace: StringToInt(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
YSpace: StringToInt(props[inc()]),
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
NameOffset: StringToInt(props[inc()]),
|
|
|
|
|
|
|
|
MonsterOk: StringToUint8(props[inc()]) == 1,
|
|
|
|
OperateRange: StringToInt(props[inc()]),
|
|
|
|
ShrineFunction: StringToInt(props[inc()]),
|
|
|
|
Restore: StringToUint8(props[inc()]) == 1,
|
|
|
|
|
2019-11-03 11:04:58 -05:00
|
|
|
Parm: [8]int{
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
StringToInt(props[inc()]),
|
|
|
|
},
|
2019-11-05 20:46:52 -05:00
|
|
|
Act: StringToInt(props[inc()]),
|
|
|
|
Lockable: StringToUint8(props[inc()]) == 1,
|
|
|
|
Gore: StringToUint8(props[inc()]) == 1,
|
|
|
|
Sync: StringToUint8(props[inc()]) == 1,
|
|
|
|
Flicker: StringToUint8(props[inc()]) == 1,
|
|
|
|
Damage: StringToInt(props[inc()]),
|
|
|
|
Beta: StringToUint8(props[inc()]) == 1,
|
|
|
|
Overlay: StringToUint8(props[inc()]) == 1,
|
|
|
|
CollisionSubst: StringToUint8(props[inc()]) == 1,
|
|
|
|
|
|
|
|
Left: StringToInt(props[inc()]),
|
|
|
|
Top: StringToInt(props[inc()]),
|
|
|
|
Width: StringToInt(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
Height: StringToInt(props[inc()]),
|
2019-11-05 20:46:52 -05:00
|
|
|
|
|
|
|
OperateFn: StringToInt(props[inc()]),
|
|
|
|
PopulateFn: StringToInt(props[inc()]),
|
|
|
|
InitFn: StringToInt(props[inc()]),
|
|
|
|
ClientFn: StringToInt(props[inc()]),
|
|
|
|
|
|
|
|
RestoreVirgins: StringToUint8(props[inc()]) == 1,
|
|
|
|
BlockMissile: StringToUint8(props[inc()]) == 1,
|
|
|
|
DrawUnder: StringToUint8(props[inc()]) == 1,
|
|
|
|
OpenWarp: StringToUint8(props[inc()]) == 1,
|
|
|
|
|
|
|
|
AutoMap: StringToInt(props[inc()]),
|
2019-11-03 11:04:58 -05:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
var Objects map[int]*ObjectRecord
|
|
|
|
|
|
|
|
func LoadObjects(fileProvider FileProvider) {
|
|
|
|
Objects = make(map[int]*ObjectRecord)
|
2019-11-06 22:12:15 -05:00
|
|
|
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.ObjectDetails)), "\r\n")[1:]
|
2019-11-03 11:04:58 -05:00
|
|
|
for _, line := range data {
|
|
|
|
if len(line) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2019-11-03 22:03:22 -05:00
|
|
|
props := strings.Split(line, "\t")
|
|
|
|
if props[2] == "" {
|
|
|
|
continue // skip a line that doesn't have an id
|
|
|
|
}
|
|
|
|
rec := createObjectRecord(props)
|
2019-11-03 11:04:58 -05:00
|
|
|
Objects[rec.Id] = &rec
|
|
|
|
}
|
|
|
|
log.Printf("Loaded %d objects", len(Objects))
|
2019-11-05 20:46:52 -05:00
|
|
|
}
|