mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-02 06:36:28 -05:00
Restructured everything. (#128)
This commit is contained in:
parent
46e163bc38
commit
b41f7f4dab
185
common/Cof.go
185
common/Cof.go
@ -1,185 +0,0 @@
|
||||
package common
|
||||
|
||||
import "strings"
|
||||
|
||||
// Tools used for go:generate.
|
||||
//
|
||||
// go get golang.org/x/tools/cmd/stringer
|
||||
// go get github.com/mewspring/tools/cmd/string2enum
|
||||
|
||||
//go:generate stringer -linecomment -type AnimationMode
|
||||
|
||||
type AnimationMode int
|
||||
|
||||
const (
|
||||
AnimationModePlayerDeath AnimationMode = 0 // DT
|
||||
AnimationModePlayerNeutral AnimationMode = 1 // NU
|
||||
AnimationModePlayerWalk AnimationMode = 2 // WL
|
||||
AnimationModePlayerRun AnimationMode = 3 // RN
|
||||
AnimationModePlayerGetHit AnimationMode = 4 // GH
|
||||
AnimationModePlayerTownNeutral AnimationMode = 5 // TN
|
||||
AnimationModePlayerTownWalk AnimationMode = 6 // TW
|
||||
AnimationModePlayerAttack1 AnimationMode = 7 // A1
|
||||
AnimationModePlayerAttack2 AnimationMode = 8 // A2
|
||||
AnimationModePlayerBlock AnimationMode = 9 // BL
|
||||
AnimationModePlayerCast AnimationMode = 10 // SC
|
||||
AnimationModePlayerThrow AnimationMode = 11 // TH
|
||||
AnimationModePlayerKick AnimationMode = 12 // KK
|
||||
AnimationModePlayerSkill1 AnimationMode = 13 // S1
|
||||
AnimationModePlayerSkill2 AnimationMode = 14 // S2
|
||||
AnimationModePlayerSkill3 AnimationMode = 15 // S3
|
||||
AnimationModePlayerSkill4 AnimationMode = 16 // S4
|
||||
AnimationModePlayerDead AnimationMode = 17 // DD
|
||||
AnimationModePlayerSequence AnimationMode = 18 // GH
|
||||
AnimationModePlayerKnockBack AnimationMode = 19 // GH
|
||||
AnimationModeMonsterDeath AnimationMode = 20 // DT
|
||||
AnimationModeMonsterNeutral AnimationMode = 21 // NU
|
||||
AnimationModeMonsterWalk AnimationMode = 22 // WL
|
||||
AnimationModeMonsterGetHit AnimationMode = 23 // GH
|
||||
AnimationModeMonsterAttack1 AnimationMode = 24 // A1
|
||||
AnimationModeMonsterAttack2 AnimationMode = 25 // A2
|
||||
AnimationModeMonsterBlock AnimationMode = 26 // BL
|
||||
AnimationModeMonsterCast AnimationMode = 27 // SC
|
||||
AnimationModeMonsterSkill1 AnimationMode = 28 // S1
|
||||
AnimationModeMonsterSkill2 AnimationMode = 29 // S2
|
||||
AnimationModeMonsterSkill3 AnimationMode = 30 // S3
|
||||
AnimationModeMonsterSkill4 AnimationMode = 31 // S4
|
||||
AnimationModeMonsterDead AnimationMode = 32 // DD
|
||||
AnimationModeMonsterKnockback AnimationMode = 33 // GH
|
||||
AnimationModeMonsterSequence AnimationMode = 34 // xx
|
||||
AnimationModeMonsterRun AnimationMode = 35 // RN
|
||||
AnimationModeObjectNeutral AnimationMode = 36 // NU
|
||||
AnimationModeObjectOperating AnimationMode = 37 // OP
|
||||
AnimationModeObjectOpened AnimationMode = 38 // ON
|
||||
AnimationModeObjectSpecial1 AnimationMode = 39 // S1
|
||||
AnimationModeObjectSpecial2 AnimationMode = 40 // S2
|
||||
AnimationModeObjectSpecial3 AnimationMode = 41 // S3
|
||||
AnimationModeObjectSpecial4 AnimationMode = 42 // S4
|
||||
AnimationModeObjectSpecial5 AnimationMode = 43 // S5
|
||||
)
|
||||
|
||||
type CompositeType int
|
||||
|
||||
const (
|
||||
CompositeTypeHead CompositeType = 0
|
||||
CompositeTypeTorso CompositeType = 1
|
||||
CompositeTypeLegs CompositeType = 2
|
||||
CompositeTypeRightArm CompositeType = 3
|
||||
CompositeTypeLeftArm CompositeType = 4
|
||||
CompositeTypeRightHand CompositeType = 5
|
||||
CompositeTypeLeftHand CompositeType = 6
|
||||
CompositeTypeShield CompositeType = 7
|
||||
CompositeTypeSpecial1 CompositeType = 8
|
||||
CompositeTypeSpecial2 CompositeType = 9
|
||||
CompositeTypeSpecial3 CompositeType = 10
|
||||
CompositeTypeSpecial4 CompositeType = 11
|
||||
CompositeTypeSpecial5 CompositeType = 12
|
||||
CompositeTypeSpecial6 CompositeType = 13
|
||||
CompositeTypeSpecial7 CompositeType = 14
|
||||
CompositeTypeSpecial8 CompositeType = 15
|
||||
CompositeTypeMax CompositeType = 16
|
||||
)
|
||||
|
||||
type DrawEffect int
|
||||
|
||||
const (
|
||||
DrawEffectPctTransparency75 = 0 //75 % transparency (colormaps 561-816 in a .pl2)
|
||||
DrawEffectPctTransparency50 = 1 //50 % transparency (colormaps 305-560 in a .pl2)
|
||||
DrawEffectPctTransparency25 = 2 //25 % transparency (colormaps 49-304 in a .pl2)
|
||||
DrawEffectScreen = 3 //Screen (colormaps 817-1072 in a .pl2)
|
||||
DrawEffectLuminance = 4 //luminance (colormaps 1073-1328 in a .pl2)
|
||||
DrawEffectBringAlphaBlending = 5 //bright alpha blending (colormaps 1457-1712 in a .pl2)
|
||||
)
|
||||
|
||||
//go:generate stringer -linecomment -type WeaponClass
|
||||
//go:generate string2enum -samepkg -linecomment -type WeaponClass
|
||||
|
||||
type WeaponClass int
|
||||
|
||||
const (
|
||||
WeaponClassNone WeaponClass = 0 //
|
||||
WeaponClassHandToHand WeaponClass = 1 // hth
|
||||
WeaponClassBow WeaponClass = 2 // bow
|
||||
WeaponClassOneHandSwing WeaponClass = 3 // 1hs
|
||||
WeaponClassOneHandThrust WeaponClass = 4 // 1ht
|
||||
WeaponClassStaff WeaponClass = 5 // stf
|
||||
WeaponClassTwoHandSwing WeaponClass = 6 // 2hs
|
||||
WeaponClassTwoHandThrust WeaponClass = 7 // 2ht
|
||||
WeaponClassCrossbow WeaponClass = 8 // xbw
|
||||
WeaponClassLeftJabRightSwing WeaponClass = 9 // 1js
|
||||
WeaponClassLeftJabRightThrust WeaponClass = 10 // 1jt
|
||||
WeaponClassLeftSwingRightSwing WeaponClass = 11 // 1ss
|
||||
WeaponClassLeftSwingRightThrust WeaponClass = 12 // 1st
|
||||
WeaponClassOneHandToHand WeaponClass = 13 // ht1
|
||||
WeaponClassTwoHandToHand WeaponClass = 14 // ht2
|
||||
)
|
||||
|
||||
type AnimationFrame int
|
||||
|
||||
const (
|
||||
AnimationFrameNoEvent AnimationFrame = 0
|
||||
AnimationFrameAttack AnimationFrame = 1
|
||||
AnimationFrameMissile AnimationFrame = 2
|
||||
AnimationFrameSound AnimationFrame = 3
|
||||
AnimationFrameSkill AnimationFrame = 4
|
||||
)
|
||||
|
||||
type CofLayer struct {
|
||||
Type CompositeType
|
||||
Shadow byte
|
||||
Transparent bool
|
||||
DrawEffect DrawEffect
|
||||
WeaponClass WeaponClass
|
||||
}
|
||||
|
||||
type Cof struct {
|
||||
NumberOfDirections int
|
||||
FramesPerDirection int
|
||||
NumberOfLayers int
|
||||
CofLayers []*CofLayer
|
||||
CompositeLayers map[CompositeType]int
|
||||
AnimationFrames []AnimationFrame
|
||||
Priority [][][]CompositeType
|
||||
}
|
||||
|
||||
func LoadCof(fileName string, fileProvider FileProvider) *Cof {
|
||||
result := &Cof{}
|
||||
fileData := fileProvider.LoadFile(fileName)
|
||||
streamReader := CreateStreamReader(fileData)
|
||||
result.NumberOfLayers = int(streamReader.GetByte())
|
||||
result.FramesPerDirection = int(streamReader.GetByte())
|
||||
result.NumberOfDirections = int(streamReader.GetByte())
|
||||
streamReader.SkipBytes(25) // Skip 25 unknown bytes...
|
||||
result.CofLayers = make([]*CofLayer, 0)
|
||||
result.CompositeLayers = make(map[CompositeType]int, 0)
|
||||
for i := 0; i < result.NumberOfLayers; i++ {
|
||||
layer := &CofLayer{}
|
||||
layer.Type = CompositeType(streamReader.GetByte())
|
||||
layer.Shadow = streamReader.GetByte()
|
||||
streamReader.SkipBytes(1) // Unknown
|
||||
layer.Transparent = streamReader.GetByte() != 0
|
||||
layer.DrawEffect = DrawEffect(streamReader.GetByte())
|
||||
weaponClassStr, _ := streamReader.ReadBytes(4)
|
||||
layer.WeaponClass = WeaponClassFromString(strings.TrimSpace(strings.ReplaceAll(string(weaponClassStr), string(0), "")))
|
||||
result.CofLayers = append(result.CofLayers, layer)
|
||||
result.CompositeLayers[layer.Type] = i
|
||||
}
|
||||
animationFrameBytes, _ := streamReader.ReadBytes(result.FramesPerDirection)
|
||||
result.AnimationFrames = make([]AnimationFrame, result.FramesPerDirection)
|
||||
for i := range animationFrameBytes {
|
||||
result.AnimationFrames[i] = AnimationFrame(animationFrameBytes[i])
|
||||
}
|
||||
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
||||
result.Priority = make([][][]CompositeType, result.NumberOfDirections)
|
||||
priorityBytes, _ := streamReader.ReadBytes(priorityLen)
|
||||
for direction := 0; direction < result.NumberOfDirections; direction++ {
|
||||
result.Priority[direction] = make([][]CompositeType, result.FramesPerDirection)
|
||||
for frame := 0; frame < result.FramesPerDirection; frame++ {
|
||||
result.Priority[direction][frame] = make([]CompositeType, result.NumberOfLayers)
|
||||
for i := 0; i < result.NumberOfLayers; i++ {
|
||||
result.Priority[direction][frame][i] = CompositeType(priorityBytes[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package common
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
|
||||
// FileProvider is an instance that can provide different types of files
|
||||
type FileProvider interface {
|
||||
LoadFile(fileName string) []byte
|
||||
LoadSprite(fileName string, palette palettedefs.PaletteType) *Sprite
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package common
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
|
||||
var MonStatsDictionary *DataDictionary
|
||||
|
||||
func LoadMonStats(fileProvider FileProvider) {
|
||||
MonStatsDictionary = LoadDataDictionary(string(fileProvider.LoadFile(resourcepaths.MonStats)))
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type NPC struct {
|
||||
AnimatedEntity *AnimatedEntity
|
||||
Paths []Path
|
||||
}
|
||||
|
||||
func CreateNPC(object Object, fileProvider FileProvider) *NPC {
|
||||
result := &NPC{
|
||||
AnimatedEntity: CreateAnimatedEntity(object, fileProvider, palettedefs.Units),
|
||||
Paths: object.Paths,
|
||||
}
|
||||
result.AnimatedEntity.SetMode(object.Lookup.Mode, object.Lookup.Class, 1, fileProvider)
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *NPC) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
v.AnimatedEntity.Render(target, offsetX, offsetY)
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package common
|
||||
|
||||
type Object struct {
|
||||
Type int32
|
||||
Id int32
|
||||
X int32
|
||||
Y int32
|
||||
Flags int32
|
||||
Paths []Path
|
||||
Lookup *ObjectLookupRecord
|
||||
ObjectInfo *ObjectRecord
|
||||
}
|
@ -1,353 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
)
|
||||
|
||||
// An ObjectRecord represents the settings for one type of object from objects.txt
|
||||
type ObjectRecord struct {
|
||||
Name string
|
||||
Description string
|
||||
Id int
|
||||
Token string // refers to what graphics this object uses
|
||||
|
||||
SpawnMax int // unused?
|
||||
Selectable [8]bool // is this mode selectable
|
||||
TrapProbability int // unused
|
||||
|
||||
SizeX int
|
||||
SizeY int
|
||||
|
||||
NTgtFX int // unknown
|
||||
NTgtFY int // unknown
|
||||
NTgtBX int // unknown
|
||||
NTgtBY int // unknown
|
||||
|
||||
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)
|
||||
CycleAnimation [8]bool // probably whether animation loops
|
||||
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
|
||||
BlockVisibility bool // only works with IsDoor
|
||||
Orientation int // unknown (1=sw, 2=nw, 3=se, 4=ne)
|
||||
Trans int // controls palette mapping
|
||||
|
||||
OrderFlag [8]int // 0 = object, 1 = floor, 2 = wall
|
||||
PreOperate bool // unknown
|
||||
HasAnimationMode [8]bool // 'Mode' in source, true if this mode is used
|
||||
|
||||
XOffset int // in pixels offset
|
||||
YOffset int
|
||||
Draw bool // if false, object isn't drawn (shadow is still drawn and player can still select though)
|
||||
|
||||
LightRed byte // if lightdiameter is set, rgb of the light
|
||||
LightGreen byte
|
||||
LightBlue byte
|
||||
|
||||
SelHD bool // whether these DCC components are selectable
|
||||
SelTR bool
|
||||
SelLG bool
|
||||
SelRA bool
|
||||
SelLA bool
|
||||
SelRH bool
|
||||
SelLH bool
|
||||
SelSH bool
|
||||
SelS [8]bool
|
||||
|
||||
TotalPieces int // selectable DCC components count
|
||||
SubClass int // subclass of object:
|
||||
// 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
|
||||
|
||||
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
|
||||
CollisionSubst bool // unknown, controls some kind of special collision checking?
|
||||
|
||||
Left int // unknown, clickable bounding box?
|
||||
Top int
|
||||
Width int
|
||||
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)
|
||||
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
|
||||
// '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
|
||||
func createObjectRecord(props []string) ObjectRecord {
|
||||
i := -1
|
||||
inc := func() int {
|
||||
i++
|
||||
return i
|
||||
}
|
||||
result := ObjectRecord{
|
||||
Name: props[inc()],
|
||||
Description: props[inc()],
|
||||
Id: StringToInt(props[inc()]),
|
||||
Token: props[inc()],
|
||||
|
||||
SpawnMax: StringToInt(props[inc()]),
|
||||
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,
|
||||
},
|
||||
TrapProbability: StringToInt(props[inc()]),
|
||||
|
||||
SizeX: StringToInt(props[inc()]),
|
||||
SizeY: StringToInt(props[inc()]),
|
||||
|
||||
NTgtFX: StringToInt(props[inc()]),
|
||||
NTgtFY: StringToInt(props[inc()]),
|
||||
NTgtBX: StringToInt(props[inc()]),
|
||||
NTgtBY: StringToInt(props[inc()]),
|
||||
|
||||
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,
|
||||
},
|
||||
IsAttackable: StringToUint8(props[inc()]) == 1,
|
||||
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()]),
|
||||
},
|
||||
|
||||
EnvEffect: StringToUint8(props[inc()]) == 1,
|
||||
IsDoor: StringToUint8(props[inc()]) == 1,
|
||||
BlockVisibility: StringToUint8(props[inc()]) == 1,
|
||||
Orientation: StringToInt(props[inc()]),
|
||||
Trans: StringToInt(props[inc()]),
|
||||
|
||||
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()]),
|
||||
},
|
||||
PreOperate: StringToUint8(props[inc()]) == 1,
|
||||
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,
|
||||
},
|
||||
|
||||
XOffset: StringToInt(props[inc()]),
|
||||
YOffset: StringToInt(props[inc()]),
|
||||
Draw: StringToUint8(props[inc()]) == 1,
|
||||
|
||||
LightRed: StringToUint8(props[inc()]),
|
||||
LightGreen: StringToUint8(props[inc()]),
|
||||
LightBlue: StringToUint8(props[inc()]),
|
||||
|
||||
SelHD: StringToUint8(props[inc()]) == 1,
|
||||
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,
|
||||
},
|
||||
|
||||
TotalPieces: StringToInt(props[inc()]),
|
||||
SubClass: StringToInt(props[inc()]),
|
||||
|
||||
XSpace: StringToInt(props[inc()]),
|
||||
YSpace: StringToInt(props[inc()]),
|
||||
|
||||
NameOffset: StringToInt(props[inc()]),
|
||||
|
||||
MonsterOk: StringToUint8(props[inc()]) == 1,
|
||||
OperateRange: StringToInt(props[inc()]),
|
||||
ShrineFunction: StringToInt(props[inc()]),
|
||||
Restore: StringToUint8(props[inc()]) == 1,
|
||||
|
||||
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()]),
|
||||
},
|
||||
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()]),
|
||||
Height: StringToInt(props[inc()]),
|
||||
|
||||
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()]),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var Objects map[int]*ObjectRecord
|
||||
|
||||
func LoadObjects(fileProvider FileProvider) {
|
||||
Objects = make(map[int]*ObjectRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.ObjectDetails)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
props := strings.Split(line, "\t")
|
||||
if props[2] == "" {
|
||||
continue // skip a line that doesn't have an id
|
||||
}
|
||||
rec := createObjectRecord(props)
|
||||
Objects[rec.Id] = &rec
|
||||
}
|
||||
log.Printf("Loaded %d objects", len(Objects))
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
package sound
|
||||
package d2audio
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/audio"
|
||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
||||
)
|
||||
|
||||
// Manager provides sound
|
||||
type Manager struct {
|
||||
fileProvider common.FileProvider
|
||||
fileProvider d2interface.FileProvider
|
||||
audioContext *audio.Context // The Audio context
|
||||
bgmAudio *audio.Player // The audio player
|
||||
lastBgm string
|
||||
@ -19,7 +20,7 @@ type Manager struct {
|
||||
}
|
||||
|
||||
// CreateManager creates a sound provider
|
||||
func CreateManager(fileProvider common.FileProvider) *Manager {
|
||||
func CreateManager(fileProvider d2interface.FileProvider) *Manager {
|
||||
result := &Manager{
|
||||
fileProvider: fileProvider,
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package sound
|
||||
package d2audio
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/audio"
|
||||
)
|
||||
@ -14,11 +16,11 @@ type SoundEffect struct {
|
||||
player *audio.Player
|
||||
}
|
||||
|
||||
func CreateSoundEffect(sfx string, fileProvider common.FileProvider, context *audio.Context, volume float64) *SoundEffect {
|
||||
func CreateSoundEffect(sfx string, fileProvider d2interface.FileProvider, context *audio.Context, volume float64) *SoundEffect {
|
||||
result := &SoundEffect{}
|
||||
var soundFile string
|
||||
if _, exists := common.Sounds[sfx]; exists {
|
||||
soundEntry := common.Sounds[sfx]
|
||||
if _, exists := datadict.Sounds[sfx]; exists {
|
||||
soundEntry := datadict.Sounds[sfx]
|
||||
soundFile = soundEntry.FileName
|
||||
} else {
|
||||
soundFile = sfx
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
type BitMuncher struct {
|
||||
data []byte
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import "log"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
type BuildInfoRecord struct {
|
||||
Branch string
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"log"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
type Path struct {
|
||||
X int32
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
type Rectangle struct {
|
||||
Left int
|
@ -1,4 +1,4 @@
|
||||
package resourcepaths
|
||||
package d2common
|
||||
|
||||
var LanguageCode string
|
||||
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"io"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
// StreamWriter allows you to create a byte array by streaming in writes of various sizes
|
||||
type StreamWriter struct {
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,10 +1,10 @@
|
||||
package common
|
||||
package d2common
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
type textDictionaryHashEntry struct {
|
||||
@ -26,16 +26,16 @@ func TranslateString(key string) string {
|
||||
return result
|
||||
}
|
||||
|
||||
func LoadTextDictionary(fileProvider FileProvider) {
|
||||
func LoadTextDictionary(fileProvider d2interface.FileProvider) {
|
||||
lookupTable = make(map[string]string)
|
||||
|
||||
loadDictionary(fileProvider, resourcepaths.PatchStringTable)
|
||||
loadDictionary(fileProvider, resourcepaths.ExpansionStringTable)
|
||||
loadDictionary(fileProvider, resourcepaths.StringTable)
|
||||
loadDictionary(fileProvider, PatchStringTable)
|
||||
loadDictionary(fileProvider, ExpansionStringTable)
|
||||
loadDictionary(fileProvider, StringTable)
|
||||
log.Printf("Loaded %d entries from the string table", len(lookupTable))
|
||||
}
|
||||
|
||||
func loadDictionary(fileProvider FileProvider, dictionaryName string) {
|
||||
func loadDictionary(fileProvider d2interface.FileProvider, dictionaryName string) {
|
||||
dictionaryData := fileProvider.LoadFile(dictionaryName)
|
||||
br := CreateStreamReader(dictionaryData)
|
||||
br.ReadBytes(2) // CRC
|
11
d2common/d2enum/AnimationFrame.go
Normal file
11
d2common/d2enum/AnimationFrame.go
Normal file
@ -0,0 +1,11 @@
|
||||
package d2enum
|
||||
|
||||
type AnimationFrame int
|
||||
|
||||
const (
|
||||
AnimationFrameNoEvent AnimationFrame = 0
|
||||
AnimationFrameAttack AnimationFrame = 1
|
||||
AnimationFrameMissile AnimationFrame = 2
|
||||
AnimationFrameSound AnimationFrame = 3
|
||||
AnimationFrameSkill AnimationFrame = 4
|
||||
)
|
52
d2common/d2enum/AnimationMode.go
Normal file
52
d2common/d2enum/AnimationMode.go
Normal file
@ -0,0 +1,52 @@
|
||||
package d2enum
|
||||
|
||||
type AnimationMode int
|
||||
|
||||
const (
|
||||
AnimationModePlayerDeath AnimationMode = 0 // DT
|
||||
AnimationModePlayerNeutral AnimationMode = 1 // NU
|
||||
AnimationModePlayerWalk AnimationMode = 2 // WL
|
||||
AnimationModePlayerRun AnimationMode = 3 // RN
|
||||
AnimationModePlayerGetHit AnimationMode = 4 // GH
|
||||
AnimationModePlayerTownNeutral AnimationMode = 5 // TN
|
||||
AnimationModePlayerTownWalk AnimationMode = 6 // TW
|
||||
AnimationModePlayerAttack1 AnimationMode = 7 // A1
|
||||
AnimationModePlayerAttack2 AnimationMode = 8 // A2
|
||||
AnimationModePlayerBlock AnimationMode = 9 // BL
|
||||
AnimationModePlayerCast AnimationMode = 10 // SC
|
||||
AnimationModePlayerThrow AnimationMode = 11 // TH
|
||||
AnimationModePlayerKick AnimationMode = 12 // KK
|
||||
AnimationModePlayerSkill1 AnimationMode = 13 // S1
|
||||
AnimationModePlayerSkill2 AnimationMode = 14 // S2
|
||||
AnimationModePlayerSkill3 AnimationMode = 15 // S3
|
||||
AnimationModePlayerSkill4 AnimationMode = 16 // S4
|
||||
AnimationModePlayerDead AnimationMode = 17 // DD
|
||||
AnimationModePlayerSequence AnimationMode = 18 // GH
|
||||
AnimationModePlayerKnockBack AnimationMode = 19 // GH
|
||||
AnimationModeMonsterDeath AnimationMode = 20 // DT
|
||||
AnimationModeMonsterNeutral AnimationMode = 21 // NU
|
||||
AnimationModeMonsterWalk AnimationMode = 22 // WL
|
||||
AnimationModeMonsterGetHit AnimationMode = 23 // GH
|
||||
AnimationModeMonsterAttack1 AnimationMode = 24 // A1
|
||||
AnimationModeMonsterAttack2 AnimationMode = 25 // A2
|
||||
AnimationModeMonsterBlock AnimationMode = 26 // BL
|
||||
AnimationModeMonsterCast AnimationMode = 27 // SC
|
||||
AnimationModeMonsterSkill1 AnimationMode = 28 // S1
|
||||
AnimationModeMonsterSkill2 AnimationMode = 29 // S2
|
||||
AnimationModeMonsterSkill3 AnimationMode = 30 // S3
|
||||
AnimationModeMonsterSkill4 AnimationMode = 31 // S4
|
||||
AnimationModeMonsterDead AnimationMode = 32 // DD
|
||||
AnimationModeMonsterKnockback AnimationMode = 33 // GH
|
||||
AnimationModeMonsterSequence AnimationMode = 34 // xx
|
||||
AnimationModeMonsterRun AnimationMode = 35 // RN
|
||||
AnimationModeObjectNeutral AnimationMode = 36 // NU
|
||||
AnimationModeObjectOperating AnimationMode = 37 // OP
|
||||
AnimationModeObjectOpened AnimationMode = 38 // ON
|
||||
AnimationModeObjectSpecial1 AnimationMode = 39 // S1
|
||||
AnimationModeObjectSpecial2 AnimationMode = 40 // S2
|
||||
AnimationModeObjectSpecial3 AnimationMode = 41 // S3
|
||||
AnimationModeObjectSpecial4 AnimationMode = 42 // S4
|
||||
AnimationModeObjectSpecial5 AnimationMode = 43 // S5
|
||||
)
|
||||
|
||||
//go:generate stringer -linecomment -type AnimationMode
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -linecomment -type AnimationMode"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
package d2enum
|
||||
|
||||
import "strconv"
|
||||
|
23
d2common/d2enum/CompositeType.go
Normal file
23
d2common/d2enum/CompositeType.go
Normal file
@ -0,0 +1,23 @@
|
||||
package d2enum
|
||||
|
||||
type CompositeType int
|
||||
|
||||
const (
|
||||
CompositeTypeHead CompositeType = 0
|
||||
CompositeTypeTorso CompositeType = 1
|
||||
CompositeTypeLegs CompositeType = 2
|
||||
CompositeTypeRightArm CompositeType = 3
|
||||
CompositeTypeLeftArm CompositeType = 4
|
||||
CompositeTypeRightHand CompositeType = 5
|
||||
CompositeTypeLeftHand CompositeType = 6
|
||||
CompositeTypeShield CompositeType = 7
|
||||
CompositeTypeSpecial1 CompositeType = 8
|
||||
CompositeTypeSpecial2 CompositeType = 9
|
||||
CompositeTypeSpecial3 CompositeType = 10
|
||||
CompositeTypeSpecial4 CompositeType = 11
|
||||
CompositeTypeSpecial5 CompositeType = 12
|
||||
CompositeTypeSpecial6 CompositeType = 13
|
||||
CompositeTypeSpecial7 CompositeType = 14
|
||||
CompositeTypeSpecial8 CompositeType = 15
|
||||
CompositeTypeMax CompositeType = 16
|
||||
)
|
12
d2common/d2enum/DrawEffect.go
Normal file
12
d2common/d2enum/DrawEffect.go
Normal file
@ -0,0 +1,12 @@
|
||||
package d2enum
|
||||
|
||||
type DrawEffect int
|
||||
|
||||
const (
|
||||
DrawEffectPctTransparency75 = 0 //75 % transparency (colormaps 561-816 in a .pl2)
|
||||
DrawEffectPctTransparency50 = 1 //50 % transparency (colormaps 305-560 in a .pl2)
|
||||
DrawEffectPctTransparency25 = 2 //25 % transparency (colormaps 49-304 in a .pl2)
|
||||
DrawEffectScreen = 3 //Screen (colormaps 817-1072 in a .pl2)
|
||||
DrawEffectLuminance = 4 //luminance (colormaps 1073-1328 in a .pl2)
|
||||
DrawEffectBringAlphaBlending = 5 //bright alpha blending (colormaps 1457-1712 in a .pl2)
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2enum
|
||||
|
||||
type Hero int
|
||||
|
11
d2common/d2enum/HeroStance.go
Normal file
11
d2common/d2enum/HeroStance.go
Normal file
@ -0,0 +1,11 @@
|
||||
package d2enum
|
||||
|
||||
type HeroStance int
|
||||
|
||||
const (
|
||||
HeroStanceIdle HeroStance = 0
|
||||
HeroStanceIdleSelected HeroStance = 1
|
||||
HeroStanceApproaching HeroStance = 2
|
||||
HeroStanceSelected HeroStance = 3
|
||||
HeroStanceRetreating HeroStance = 4
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package _map
|
||||
package d2enum
|
||||
|
||||
type Orientation int32
|
||||
|
@ -1,4 +1,4 @@
|
||||
package palettedefs
|
||||
package d2enum
|
||||
|
||||
// PaletteType represents a named palette
|
||||
type PaletteType string
|
24
d2common/d2enum/WeaponClass.go
Normal file
24
d2common/d2enum/WeaponClass.go
Normal file
@ -0,0 +1,24 @@
|
||||
package d2enum
|
||||
|
||||
type WeaponClass int
|
||||
|
||||
const (
|
||||
WeaponClassNone WeaponClass = 0 //
|
||||
WeaponClassHandToHand WeaponClass = 1 // hth
|
||||
WeaponClassBow WeaponClass = 2 // bow
|
||||
WeaponClassOneHandSwing WeaponClass = 3 // 1hs
|
||||
WeaponClassOneHandThrust WeaponClass = 4 // 1ht
|
||||
WeaponClassStaff WeaponClass = 5 // stf
|
||||
WeaponClassTwoHandSwing WeaponClass = 6 // 2hs
|
||||
WeaponClassTwoHandThrust WeaponClass = 7 // 2ht
|
||||
WeaponClassCrossbow WeaponClass = 8 // xbw
|
||||
WeaponClassLeftJabRightSwing WeaponClass = 9 // 1js
|
||||
WeaponClassLeftJabRightThrust WeaponClass = 10 // 1jt
|
||||
WeaponClassLeftSwingRightSwing WeaponClass = 11 // 1ss
|
||||
WeaponClassLeftSwingRightThrust WeaponClass = 12 // 1st
|
||||
WeaponClassOneHandToHand WeaponClass = 13 // ht1
|
||||
WeaponClassTwoHandToHand WeaponClass = 14 // ht2
|
||||
)
|
||||
|
||||
//go:generate stringer -linecomment -type WeaponClass
|
||||
//go:generate string2enum -samepkg -linecomment -type WeaponClass
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -linecomment -type WeaponClass"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
package d2enum
|
||||
|
||||
import "strconv"
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "string2enum -samepkg -linecomment -type WeaponClass"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
package d2enum
|
||||
|
||||
import "fmt"
|
||||
|
17
d2common/d2enum/readme.md
Normal file
17
d2common/d2enum/readme.md
Normal file
@ -0,0 +1,17 @@
|
||||
# OpenDiablo2 Enums
|
||||
Items in this folder are compiled with two programs. You can obtain them
|
||||
by running the following:
|
||||
```
|
||||
go get golang.org/x/tools/cmd/stringer
|
||||
go get github.com/mewspring/tools/cmd/string2enum
|
||||
```
|
||||
Once you have the tools installed, simply run the following command in this
|
||||
folder to regenerate the support files:
|
||||
```
|
||||
generate
|
||||
```
|
||||
If you add any new files, make sure to add the following to the end of the
|
||||
file:
|
||||
```go
|
||||
//go:generate stringer -linecomment -type AnimationMode
|
||||
```
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2interface
|
||||
|
||||
import "github.com/hajimehoshi/ebiten"
|
||||
|
7
d2common/d2interface/FileProvider.go
Normal file
7
d2common/d2interface/FileProvider.go
Normal file
@ -0,0 +1,7 @@
|
||||
package d2interface
|
||||
|
||||
// FileProvider is an instance that can provide different types of files
|
||||
type FileProvider interface {
|
||||
LoadFile(fileName string) []byte
|
||||
//LoadSprite(fileName string, palette enums.PaletteType) *d2render.Sprite
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package scenes
|
||||
package d2interface
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
@ -1,4 +1,4 @@
|
||||
package scenes
|
||||
package d2interface
|
||||
|
||||
// SceneProvider provides the ability to change scenes
|
||||
type SceneProvider interface {
|
@ -1,4 +1,4 @@
|
||||
package core
|
||||
package d2core
|
||||
|
||||
import (
|
||||
"log"
|
||||
@ -10,16 +10,24 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/mpq"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/scenes"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/mpq"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
@ -28,20 +36,20 @@ import (
|
||||
|
||||
// Engine is the core OpenDiablo2 engine
|
||||
type Engine struct {
|
||||
Settings *common.Configuration // Engine configuration settings from json file
|
||||
Files map[string]string // Map that defines which files are in which MPQs
|
||||
CheckedPatch map[string]bool // First time we check a file, we'll check if it's in the patch. This notes that we've already checked that.
|
||||
LoadingSprite *common.Sprite // The sprite shown when loading stuff
|
||||
loadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
loadingIndex int // Determines which load function is currently being called
|
||||
thingsToLoad []func() // The load functions for the next scene
|
||||
stepLoadingSize float64 // The size for each loading step
|
||||
CurrentScene scenes.Scene // The current scene being rendered
|
||||
UIManager *ui.Manager // The UI manager
|
||||
SoundManager *sound.Manager // The sound manager
|
||||
nextScene scenes.Scene // The next scene to be loaded at the end of the game loop
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
lastTime float64 // Last time we updated the scene
|
||||
Settings *d2common.Configuration // Engine configuration settings from json file
|
||||
Files map[string]string // Map that defines which files are in which MPQs
|
||||
CheckedPatch map[string]bool // First time we check a file, we'll check if it's in the patch. This notes that we've already checked that.
|
||||
LoadingSprite *d2render.Sprite // The sprite shown when loading stuff
|
||||
loadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
loadingIndex int // Determines which load function is currently being called
|
||||
thingsToLoad []func() // The load functions for the next scene
|
||||
stepLoadingSize float64 // The size for each loading step
|
||||
CurrentScene d2interface.Scene // The current scene being rendered
|
||||
UIManager *ui.Manager // The UI manager
|
||||
SoundManager *d2audio.Manager // The sound manager
|
||||
nextScene d2interface.Scene // The next scene to be loaded at the end of the game loop
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
lastTime float64 // Last time we updated the scene
|
||||
showFPS bool
|
||||
}
|
||||
|
||||
@ -52,36 +60,35 @@ func CreateEngine() *Engine {
|
||||
nextScene: nil,
|
||||
}
|
||||
result.loadConfigurationFile()
|
||||
resourcepaths.LanguageCode = result.Settings.Language
|
||||
d2common.LanguageCode = result.Settings.Language
|
||||
result.mapMpqFiles()
|
||||
common.LoadPalettes(result.Files, result)
|
||||
common.LoadTextDictionary(result)
|
||||
common.LoadLevelTypes(result)
|
||||
common.LoadLevelPresets(result)
|
||||
common.LoadLevelWarps(result)
|
||||
common.LoadObjectTypes(result)
|
||||
common.LoadObjects(result)
|
||||
common.LoadWeapons(result)
|
||||
common.LoadArmors(result)
|
||||
common.LoadUniqueItems(result)
|
||||
common.LoadMissiles(result)
|
||||
common.LoadSounds(result)
|
||||
common.LoadAnimationData(result)
|
||||
common.LoadMonStats(result)
|
||||
result.SoundManager = sound.CreateManager(result)
|
||||
datadict.LoadPalettes(result.Files, result)
|
||||
d2common.LoadTextDictionary(result)
|
||||
datadict.LoadLevelTypes(result)
|
||||
datadict.LoadLevelPresets(result)
|
||||
datadict.LoadLevelWarps(result)
|
||||
datadict.LoadObjectTypes(result)
|
||||
datadict.LoadObjects(result)
|
||||
datadict.LoadWeapons(result)
|
||||
datadict.LoadArmors(result)
|
||||
datadict.LoadUniqueItems(result)
|
||||
datadict.LoadMissiles(result)
|
||||
datadict.LoadSounds(result)
|
||||
d2data.LoadAnimationData(result)
|
||||
datadict.LoadMonStats(result)
|
||||
result.SoundManager = d2audio.CreateManager(result)
|
||||
result.SoundManager.SetVolumes(result.Settings.BgmVolume, result.Settings.SfxVolume)
|
||||
result.UIManager = ui.CreateManager(result, *result.SoundManager)
|
||||
result.LoadingSprite = result.LoadSprite(resourcepaths.LoadingScreen, palettedefs.Loading)
|
||||
result.LoadingSprite = result.LoadSprite(d2common.LoadingScreen, d2enum.Loading)
|
||||
loadingSpriteSizeX, loadingSpriteSizeY := result.LoadingSprite.GetSize()
|
||||
result.LoadingSprite.MoveTo(int(400-(loadingSpriteSizeX/2)), int(300+(loadingSpriteSizeY/2)))
|
||||
result.SetNextScene(scenes.CreateMainMenu(result, result, result.UIManager, result.SoundManager))
|
||||
//result.SetNextScene(Scenes.CreateBlizzardIntro(result, result))
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *Engine) loadConfigurationFile() {
|
||||
log.Println("Loading configuration file")
|
||||
v.Settings = common.LoadConfiguration()
|
||||
v.Settings = d2common.LoadConfiguration()
|
||||
}
|
||||
|
||||
func (v *Engine) mapMpqFiles() {
|
||||
@ -91,7 +98,7 @@ func (v *Engine) mapMpqFiles() {
|
||||
var mutex sync.Mutex
|
||||
|
||||
func (v *Engine) LoadFile(fileName string) []byte {
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", resourcepaths.LanguageCode)
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", d2common.LanguageCode)
|
||||
fileName = strings.ToLower(fileName)
|
||||
fileName = strings.ReplaceAll(fileName, `/`, "\\")
|
||||
if fileName[0] == '\\' {
|
||||
@ -131,9 +138,9 @@ func (v *Engine) IsLoading() bool {
|
||||
}
|
||||
|
||||
// LoadSprite loads a sprite from the game's data files
|
||||
func (v *Engine) LoadSprite(fileName string, palette palettedefs.PaletteType) *common.Sprite {
|
||||
func (v *Engine) LoadSprite(fileName string, palette d2enum.PaletteType) *d2render.Sprite {
|
||||
data := v.LoadFile(fileName)
|
||||
sprite := common.CreateSprite(data, common.Palettes[palette])
|
||||
sprite := d2render.CreateSprite(data, datadict.Palettes[palette])
|
||||
return sprite
|
||||
}
|
||||
|
||||
@ -208,7 +215,7 @@ func (v *Engine) Update() {
|
||||
// Draw draws the game
|
||||
func (v *Engine) Draw(screen *ebiten.Image) {
|
||||
if v.loadingProgress < 1.0 {
|
||||
v.LoadingSprite.Frame = uint8(common.Max(0, common.Min(uint32(len(v.LoadingSprite.Frames)-1), uint32(float64(len(v.LoadingSprite.Frames)-1)*v.loadingProgress))))
|
||||
v.LoadingSprite.Frame = uint8(d2helper.Max(0, d2helper.Min(uint32(len(v.LoadingSprite.Frames)-1), uint32(float64(len(v.LoadingSprite.Frames)-1)*v.loadingProgress))))
|
||||
v.LoadingSprite.Draw(screen)
|
||||
} else {
|
||||
if v.CurrentScene == nil {
|
||||
@ -223,7 +230,7 @@ func (v *Engine) Draw(screen *ebiten.Image) {
|
||||
}
|
||||
|
||||
// SetNextScene tells the engine what scene to load on the next update cycle
|
||||
func (v *Engine) SetNextScene(nextScene scenes.Scene) {
|
||||
func (v *Engine) SetNextScene(nextScene d2interface.Scene) {
|
||||
v.nextScene = nextScene
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2core
|
||||
|
||||
import (
|
||||
"log"
|
@ -1,18 +1,18 @@
|
||||
package scenes
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/video"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/video"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type BlizzardIntro struct {
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
videoDecoder *video.BinkDecoder
|
||||
}
|
||||
|
||||
func CreateBlizzardIntro(fileProvider common.FileProvider, sceneProvider SceneProvider) *BlizzardIntro {
|
||||
func CreateBlizzardIntro(fileProvider d2interface.FileProvider, sceneProvider d2interface.SceneProvider) *BlizzardIntro {
|
||||
result := &BlizzardIntro{
|
||||
fileProvider: fileProvider,
|
||||
sceneProvider: sceneProvider,
|
@ -1,20 +1,23 @@
|
||||
package scenes
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type CharacterSelect struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *sound.Manager
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
background *common.Sprite
|
||||
soundManager *d2audio.Manager
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
background *d2render.Sprite
|
||||
newCharButton *ui.Button
|
||||
convertCharButton *ui.Button
|
||||
deleteCharButton *ui.Button
|
||||
@ -23,10 +26,10 @@ type CharacterSelect struct {
|
||||
}
|
||||
|
||||
func CreateCharacterSelect(
|
||||
fileProvider common.FileProvider,
|
||||
sceneProvider SceneProvider,
|
||||
fileProvider d2interface.FileProvider,
|
||||
sceneProvider d2interface.SceneProvider,
|
||||
uiManager *ui.Manager,
|
||||
soundManager *sound.Manager,
|
||||
soundManager *d2audio.Manager,
|
||||
) *CharacterSelect {
|
||||
result := &CharacterSelect{
|
||||
uiManager: uiManager,
|
||||
@ -38,38 +41,38 @@ func CreateCharacterSelect(
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Load() []func() {
|
||||
v.soundManager.PlayBGM(resourcepaths.BGMTitle)
|
||||
v.soundManager.PlayBGM(d2common.BGMTitle)
|
||||
return []func(){
|
||||
func() {
|
||||
v.background = v.fileProvider.LoadSprite(resourcepaths.CharacterSelectionBackground, palettedefs.Sky)
|
||||
v.background = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.CharacterSelectionBackground), datadict.Palettes[d2enum.Sky])
|
||||
v.background.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.newCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, common.CombineStrings(common.SplitIntoLinesWithMaxWidth(common.TranslateString("#831"), 15)))
|
||||
v.newCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, dh.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#831"), 15)))
|
||||
v.newCharButton.MoveTo(33, 468)
|
||||
v.newCharButton.OnActivated(func() { v.onNewCharButtonClicked() })
|
||||
v.uiManager.AddWidget(v.newCharButton)
|
||||
},
|
||||
func() {
|
||||
v.convertCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, common.CombineStrings(common.SplitIntoLinesWithMaxWidth(common.TranslateString("#825"), 15)))
|
||||
v.convertCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, dh.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#825"), 15)))
|
||||
v.convertCharButton.MoveTo(233, 468)
|
||||
v.convertCharButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.convertCharButton)
|
||||
},
|
||||
func() {
|
||||
v.deleteCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, common.CombineStrings(common.SplitIntoLinesWithMaxWidth(common.TranslateString("#832"), 15)))
|
||||
v.deleteCharButton = ui.CreateButton(ui.ButtonTypeTall, v.fileProvider, dh.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#832"), 15)))
|
||||
v.deleteCharButton.MoveTo(433, 468)
|
||||
v.deleteCharButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.deleteCharButton)
|
||||
},
|
||||
func() {
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, common.TranslateString("#970"))
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, d2common.TranslateString("#970"))
|
||||
v.exitButton.MoveTo(33, 537)
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitButton)
|
||||
},
|
||||
func() {
|
||||
v.okButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, common.TranslateString("#971"))
|
||||
v.okButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, d2common.TranslateString("#971"))
|
||||
v.okButton.MoveTo(625, 537)
|
||||
v.okButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.okButton)
|
@ -4,11 +4,18 @@ import (
|
||||
"image/color"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -21,10 +28,10 @@ type labelItem struct {
|
||||
// Credits represents the credits scene
|
||||
type Credits struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *sound.Manager
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
creditsBackground *common.Sprite
|
||||
soundManager *d2audio.Manager
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
creditsBackground *d2render.Sprite
|
||||
exitButton *ui.Button
|
||||
creditsText []string
|
||||
labels []*labelItem
|
||||
@ -34,7 +41,7 @@ type Credits struct {
|
||||
}
|
||||
|
||||
// CreateCredits creates an instance of the credits scene
|
||||
func CreateCredits(fileProvider common.FileProvider, sceneProvider SceneProvider, uiManager *ui.Manager, soundManager *sound.Manager) *Credits {
|
||||
func CreateCredits(fileProvider d2interface.FileProvider, sceneProvider d2interface.SceneProvider, uiManager *ui.Manager, soundManager *d2audio.Manager) *Credits {
|
||||
result := &Credits{
|
||||
fileProvider: fileProvider,
|
||||
uiManager: uiManager,
|
||||
@ -52,17 +59,17 @@ func CreateCredits(fileProvider common.FileProvider, sceneProvider SceneProvider
|
||||
func (v *Credits) Load() []func() {
|
||||
return []func(){
|
||||
func() {
|
||||
v.creditsBackground = v.fileProvider.LoadSprite(resourcepaths.CreditsBackground, palettedefs.Sky)
|
||||
v.creditsBackground = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.CreditsBackground), datadict.Palettes[d2enum.Sky])
|
||||
v.creditsBackground.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, common.TranslateString("#970"))
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, d2common.TranslateString("#970"))
|
||||
v.exitButton.MoveTo(30, 550)
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitButton)
|
||||
},
|
||||
func() {
|
||||
fileData, _ := common.Utf16BytesToString(v.fileProvider.LoadFile(resourcepaths.CreditsText)[2:])
|
||||
fileData, _ := dh.Utf16BytesToString(v.fileProvider.LoadFile(d2common.CreditsText)[2:])
|
||||
v.creditsText = strings.Split(fileData, "\r\n")
|
||||
for i := range v.creditsText {
|
||||
v.creditsText[i] = strings.Trim(v.creditsText[i], " ")
|
||||
@ -190,7 +197,7 @@ func (v *Credits) getNewFontLabel(isHeading bool) *ui.Label {
|
||||
newLabelItem := &labelItem{
|
||||
Available: false,
|
||||
IsHeading: isHeading,
|
||||
Label: ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal10, palettedefs.Sky),
|
||||
Label: ui.CreateLabel(v.fileProvider, d2common.FontFormal10, d2enum.Sky),
|
||||
}
|
||||
|
||||
if isHeading {
|
@ -8,27 +8,33 @@ import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
// MainMenu represents the main menu
|
||||
type MainMenu struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *sound.Manager
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
trademarkBackground *common.Sprite
|
||||
background *common.Sprite
|
||||
diabloLogoLeft *common.Sprite
|
||||
diabloLogoRight *common.Sprite
|
||||
diabloLogoLeftBack *common.Sprite
|
||||
diabloLogoRightBack *common.Sprite
|
||||
soundManager *d2audio.Manager
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
trademarkBackground *d2render.Sprite
|
||||
background *d2render.Sprite
|
||||
diabloLogoLeft *d2render.Sprite
|
||||
diabloLogoRight *d2render.Sprite
|
||||
diabloLogoLeftBack *d2render.Sprite
|
||||
diabloLogoRightBack *d2render.Sprite
|
||||
singlePlayerButton *ui.Button
|
||||
githubButton *ui.Button
|
||||
exitDiabloButton *ui.Button
|
||||
@ -46,7 +52,7 @@ type MainMenu struct {
|
||||
}
|
||||
|
||||
// CreateMainMenu creates an instance of MainMenu
|
||||
func CreateMainMenu(fileProvider common.FileProvider, sceneProvider SceneProvider, uiManager *ui.Manager, soundManager *sound.Manager) *MainMenu {
|
||||
func CreateMainMenu(fileProvider d2interface.FileProvider, sceneProvider d2interface.SceneProvider, uiManager *ui.Manager, soundManager *d2audio.Manager) *MainMenu {
|
||||
result := &MainMenu{
|
||||
fileProvider: fileProvider,
|
||||
uiManager: uiManager,
|
||||
@ -60,93 +66,93 @@ func CreateMainMenu(fileProvider common.FileProvider, sceneProvider SceneProvide
|
||||
|
||||
// Load is called to load the resources for the main menu
|
||||
func (v *MainMenu) Load() []func() {
|
||||
v.soundManager.PlayBGM(resourcepaths.BGMTitle)
|
||||
v.soundManager.PlayBGM(d2common.BGMTitle)
|
||||
return []func(){
|
||||
func() {
|
||||
v.versionLabel = ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal12, palettedefs.Static)
|
||||
v.versionLabel = ui.CreateLabel(v.fileProvider, d2common.FontFormal12, d2enum.Static)
|
||||
v.versionLabel.Alignment = ui.LabelAlignRight
|
||||
v.versionLabel.SetText("OpenDiablo2 - " + common.BuildInfo.Branch)
|
||||
v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch)
|
||||
v.versionLabel.Color = color.RGBA{255, 255, 255, 255}
|
||||
v.versionLabel.MoveTo(795, -10)
|
||||
},
|
||||
func() {
|
||||
v.commitLabel = ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal10, palettedefs.Static)
|
||||
v.commitLabel = ui.CreateLabel(v.fileProvider, d2common.FontFormal10, d2enum.Static)
|
||||
v.commitLabel.Alignment = ui.LabelAlignLeft
|
||||
v.commitLabel.SetText(common.BuildInfo.Commit)
|
||||
v.commitLabel.SetText(d2common.BuildInfo.Commit)
|
||||
v.commitLabel.Color = color.RGBA{255, 255, 255, 255}
|
||||
v.commitLabel.MoveTo(2, 2)
|
||||
},
|
||||
func() {
|
||||
v.copyrightLabel = ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal12, palettedefs.Static)
|
||||
v.copyrightLabel = ui.CreateLabel(v.fileProvider, d2common.FontFormal12, d2enum.Static)
|
||||
v.copyrightLabel.Alignment = ui.LabelAlignCenter
|
||||
v.copyrightLabel.SetText("Diablo 2 is © Copyright 2000-2016 Blizzard Entertainment")
|
||||
v.copyrightLabel.Color = color.RGBA{188, 168, 140, 255}
|
||||
v.copyrightLabel.MoveTo(400, 500)
|
||||
},
|
||||
func() {
|
||||
v.copyrightLabel2 = ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal12, palettedefs.Static)
|
||||
v.copyrightLabel2 = ui.CreateLabel(v.fileProvider, d2common.FontFormal12, d2enum.Static)
|
||||
v.copyrightLabel2.Alignment = ui.LabelAlignCenter
|
||||
v.copyrightLabel2.SetText(common.TranslateString("#1614"))
|
||||
v.copyrightLabel2.SetText(d2common.TranslateString("#1614"))
|
||||
v.copyrightLabel2.Color = color.RGBA{188, 168, 140, 255}
|
||||
v.copyrightLabel2.MoveTo(400, 525)
|
||||
},
|
||||
func() {
|
||||
v.openDiabloLabel = ui.CreateLabel(v.fileProvider, resourcepaths.FontFormal10, palettedefs.Static)
|
||||
v.openDiabloLabel = ui.CreateLabel(v.fileProvider, d2common.FontFormal10, d2enum.Static)
|
||||
v.openDiabloLabel.Alignment = ui.LabelAlignCenter
|
||||
v.openDiabloLabel.SetText("OpenDiablo2 is neither developed by, nor endorsed by Blizzard or its parent company Activision")
|
||||
v.openDiabloLabel.Color = color.RGBA{255, 255, 140, 255}
|
||||
v.openDiabloLabel.MoveTo(400, 580)
|
||||
},
|
||||
func() {
|
||||
v.background = v.fileProvider.LoadSprite(resourcepaths.GameSelectScreen, palettedefs.Sky)
|
||||
v.background = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.GameSelectScreen), datadict.Palettes[d2enum.Sky])
|
||||
v.background.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.trademarkBackground = v.fileProvider.LoadSprite(resourcepaths.TrademarkScreen, palettedefs.Sky)
|
||||
v.trademarkBackground = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.TrademarkScreen), datadict.Palettes[d2enum.Sky])
|
||||
v.trademarkBackground.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.diabloLogoLeft = v.fileProvider.LoadSprite(resourcepaths.Diablo2LogoFireLeft, palettedefs.Units)
|
||||
v.diabloLogoLeft = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.Diablo2LogoFireLeft), datadict.Palettes[d2enum.Units])
|
||||
v.diabloLogoLeft.Blend = true
|
||||
v.diabloLogoLeft.Animate = true
|
||||
v.diabloLogoLeft.MoveTo(400, 120)
|
||||
},
|
||||
func() {
|
||||
v.diabloLogoRight = v.fileProvider.LoadSprite(resourcepaths.Diablo2LogoFireRight, palettedefs.Units)
|
||||
v.diabloLogoRight = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.Diablo2LogoFireRight), datadict.Palettes[d2enum.Units])
|
||||
v.diabloLogoRight.Blend = true
|
||||
v.diabloLogoRight.Animate = true
|
||||
v.diabloLogoRight.MoveTo(400, 120)
|
||||
},
|
||||
func() {
|
||||
v.diabloLogoLeftBack = v.fileProvider.LoadSprite(resourcepaths.Diablo2LogoBlackLeft, palettedefs.Units)
|
||||
v.diabloLogoLeftBack = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.Diablo2LogoBlackLeft), datadict.Palettes[d2enum.Units])
|
||||
v.diabloLogoLeftBack.MoveTo(400, 120)
|
||||
},
|
||||
func() {
|
||||
v.diabloLogoRightBack = v.fileProvider.LoadSprite(resourcepaths.Diablo2LogoBlackRight, palettedefs.Units)
|
||||
v.diabloLogoRightBack = d2render.CreateSprite(v.fileProvider.LoadFile(d2common.Diablo2LogoBlackRight), datadict.Palettes[d2enum.Units])
|
||||
v.diabloLogoRightBack.MoveTo(400, 120)
|
||||
},
|
||||
func() {
|
||||
v.exitDiabloButton = ui.CreateButton(ui.ButtonTypeWide, v.fileProvider, common.TranslateString("#1625"))
|
||||
v.exitDiabloButton = ui.CreateButton(ui.ButtonTypeWide, v.fileProvider, d2common.TranslateString("#1625"))
|
||||
v.exitDiabloButton.MoveTo(264, 535)
|
||||
v.exitDiabloButton.SetVisible(!v.ShowTrademarkScreen)
|
||||
v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitDiabloButton)
|
||||
},
|
||||
func() {
|
||||
v.creditsButton = ui.CreateButton(ui.ButtonTypeShort, v.fileProvider, common.TranslateString("#1627"))
|
||||
v.creditsButton = ui.CreateButton(ui.ButtonTypeShort, v.fileProvider, d2common.TranslateString("#1627"))
|
||||
v.creditsButton.MoveTo(264, 505)
|
||||
v.creditsButton.SetVisible(!v.ShowTrademarkScreen)
|
||||
v.creditsButton.OnActivated(func() { v.onCreditsButtonClicked() })
|
||||
v.uiManager.AddWidget(v.creditsButton)
|
||||
},
|
||||
func() {
|
||||
v.cinematicsButton = ui.CreateButton(ui.ButtonTypeShort, v.fileProvider, common.TranslateString("#1639"))
|
||||
v.cinematicsButton = ui.CreateButton(ui.ButtonTypeShort, v.fileProvider, d2common.TranslateString("#1639"))
|
||||
v.cinematicsButton.MoveTo(401, 505)
|
||||
v.cinematicsButton.SetVisible(!v.ShowTrademarkScreen)
|
||||
v.uiManager.AddWidget(v.cinematicsButton)
|
||||
},
|
||||
func() {
|
||||
v.singlePlayerButton = ui.CreateButton(ui.ButtonTypeWide, v.fileProvider, common.TranslateString("#1620"))
|
||||
v.singlePlayerButton = ui.CreateButton(ui.ButtonTypeWide, v.fileProvider, d2common.TranslateString("#1620"))
|
||||
v.singlePlayerButton.MoveTo(264, 290)
|
||||
v.singlePlayerButton.SetVisible(!v.ShowTrademarkScreen)
|
||||
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
|
||||
@ -194,7 +200,6 @@ func openbrowser(url string) {
|
||||
|
||||
func (v *MainMenu) onSinglePlayerClicked() {
|
||||
// Go here only if existing characters are available to select
|
||||
//v.sceneProvider.SetNextScene(CreateCharacterSelect(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
v.sceneProvider.SetNextScene(CreateSelectHeroClass(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
}
|
||||
|
@ -4,35 +4,40 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
_map "github.com/OpenDiablo2/OpenDiablo2/map"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
_map "github.com/OpenDiablo2/OpenDiablo2/d2render/mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
)
|
||||
|
||||
type MapEngineTest struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *sound.Manager
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
gameState *common.GameState
|
||||
soundManager *d2audio.Manager
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
gameState *d2core.GameState
|
||||
mapEngine *_map.Engine
|
||||
}
|
||||
|
||||
func CreateMapEngineTest(
|
||||
fileProvider common.FileProvider,
|
||||
sceneProvider SceneProvider,
|
||||
fileProvider d2interface.FileProvider,
|
||||
sceneProvider d2interface.SceneProvider,
|
||||
uiManager *ui.Manager,
|
||||
soundManager *sound.Manager) *MapEngineTest {
|
||||
soundManager *d2audio.Manager) *MapEngineTest {
|
||||
result := &MapEngineTest{
|
||||
fileProvider: fileProvider,
|
||||
uiManager: uiManager,
|
||||
soundManager: soundManager,
|
||||
sceneProvider: sceneProvider,
|
||||
}
|
||||
result.gameState = common.CreateGameState()
|
||||
result.gameState = d2core.CreateGameState()
|
||||
return result
|
||||
}
|
||||
|
||||
@ -70,7 +75,7 @@ func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
||||
v.mapEngine.Render(screen)
|
||||
actualX := float64(v.uiManager.CursorX) - v.mapEngine.OffsetX
|
||||
actualY := float64(v.uiManager.CursorY) - v.mapEngine.OffsetY
|
||||
tileX, tileY := common.ScreenToIso(actualX, actualY)
|
||||
tileX, tileY := d2helper.ScreenToIso(actualX, actualY)
|
||||
subtileX := int(math.Ceil(math.Mod((tileX*10), 10))) / 2
|
||||
subtileY := int(math.Ceil(math.Mod((tileY*10), 10))) / 2
|
||||
curRegion := v.mapEngine.GetRegionAt(int(tileX), int(tileY))
|
568
d2core/scenes/SelectHeroClass.go
Normal file
568
d2core/scenes/SelectHeroClass.go
Normal file
@ -0,0 +1,568 @@
|
||||
package scenes
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type HeroRenderInfo struct {
|
||||
Stance d2enum.HeroStance
|
||||
IdleSprite *d2render.Sprite
|
||||
IdleSelectedSprite *d2render.Sprite
|
||||
ForwardWalkSprite *d2render.Sprite
|
||||
ForwardWalkSpriteOverlay *d2render.Sprite
|
||||
SelectedSprite *d2render.Sprite
|
||||
SelectedSpriteOverlay *d2render.Sprite
|
||||
BackWalkSprite *d2render.Sprite
|
||||
BackWalkSpriteOverlay *d2render.Sprite
|
||||
SelectionBounds image.Rectangle
|
||||
SelectSfx *d2audio.SoundEffect
|
||||
DeselectSfx *d2audio.SoundEffect
|
||||
}
|
||||
|
||||
type SelectHeroClass struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *d2audio.Manager
|
||||
fileProvider d2interface.FileProvider
|
||||
sceneProvider d2interface.SceneProvider
|
||||
bgImage *d2render.Sprite
|
||||
campfire *d2render.Sprite
|
||||
headingLabel *ui.Label
|
||||
heroClassLabel *ui.Label
|
||||
heroDesc1Label *ui.Label
|
||||
heroDesc2Label *ui.Label
|
||||
heroDesc3Label *ui.Label
|
||||
heroRenderInfo map[d2enum.Hero]*HeroRenderInfo
|
||||
selectedHero d2enum.Hero
|
||||
exitButton *ui.Button
|
||||
}
|
||||
|
||||
func CreateSelectHeroClass(
|
||||
fileProvider d2interface.FileProvider,
|
||||
sceneProvider d2interface.SceneProvider,
|
||||
uiManager *ui.Manager, soundManager *d2audio.Manager,
|
||||
) *SelectHeroClass {
|
||||
result := &SelectHeroClass{
|
||||
uiManager: uiManager,
|
||||
sceneProvider: sceneProvider,
|
||||
fileProvider: fileProvider,
|
||||
soundManager: soundManager,
|
||||
heroRenderInfo: make(map[d2enum.Hero]*HeroRenderInfo),
|
||||
selectedHero: d2enum.HeroNone,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) loadSprite(path string, palette d2enum.PaletteType) *d2render.Sprite {
|
||||
return d2render.CreateSprite(v.fileProvider.LoadFile(path), datadict.Palettes[palette])
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Load() []func() {
|
||||
v.soundManager.PlayBGM(d2common.BGMTitle)
|
||||
return []func(){
|
||||
func() {
|
||||
v.bgImage = v.loadSprite(d2common.CharacterSelectBackground, d2enum.Fechar)
|
||||
v.bgImage.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.headingLabel = ui.CreateLabel(v.fileProvider, d2common.Font30, d2enum.Units)
|
||||
fontWidth, _ := v.headingLabel.GetSize()
|
||||
v.headingLabel.MoveTo(400-int(fontWidth/2), 17)
|
||||
v.headingLabel.SetText("Select Hero Class")
|
||||
v.headingLabel.Alignment = ui.LabelAlignCenter
|
||||
},
|
||||
func() {
|
||||
v.heroClassLabel = ui.CreateLabel(v.fileProvider, d2common.Font30, d2enum.Units)
|
||||
v.heroClassLabel.Alignment = ui.LabelAlignCenter
|
||||
v.heroClassLabel.MoveTo(400, 65)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc1Label = ui.CreateLabel(v.fileProvider, d2common.Font16, d2enum.Units)
|
||||
v.heroDesc1Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc1Label.MoveTo(400, 100)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc2Label = ui.CreateLabel(v.fileProvider, d2common.Font16, d2enum.Units)
|
||||
v.heroDesc2Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc2Label.MoveTo(400, 115)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc3Label = ui.CreateLabel(v.fileProvider, d2common.Font16, d2enum.Units)
|
||||
v.heroDesc3Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc3Label.MoveTo(400, 130)
|
||||
},
|
||||
func() {
|
||||
v.campfire = v.loadSprite(d2common.CharacterSelectCampfire, d2enum.Fechar)
|
||||
v.campfire.MoveTo(380, 335)
|
||||
v.campfire.Animate = true
|
||||
v.campfire.Blend = true
|
||||
},
|
||||
func() {
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, d2common.TranslateString("#970"))
|
||||
v.exitButton.MoveTo(33, 537)
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitButton)
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianForwardWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianForwardWalkOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianSelected, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelectBarbarianBackWalk, d2enum.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{364, 201}, Max: image.Point{90, 170}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXBarbarianSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXBarbarianDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].IdleSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].IdleSelectedSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSprite.SpecialFrameTime = 2500
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSpriteOverlay.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSpriteOverlay.SpecialFrameTime = 2500
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].SelectedSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.SpecialFrameTime = 1000
|
||||
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroSorceress] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelecSorceressUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressForwardWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressForwardWalkOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressSelected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressSelectedOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressBackWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecSorceressBackWalkOverlay, d2enum.Fechar),
|
||||
image.Rectangle{Min: image.Point{580, 240}, Max: image.Point{65, 160}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXSorceressSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXSorceressDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].IdleSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].IdleSelectedSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSprite.SpecialFrameTime = 2300
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSpriteOverlay.SpecialFrameTime = 2300
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].SelectedSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].SelectedSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].SelectedSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].SelectedSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSprite.SpecialFrameTime = 1200
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.SpecialFrameTime = 1200
|
||||
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectNecromancerUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectNecromancerUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerForwardWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerForwardWalkOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerSelected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerSelectedOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerBackWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecNecromancerBackWalkOverlay, d2enum.Fechar),
|
||||
image.Rectangle{Min: image.Point{265, 220}, Max: image.Point{55, 175}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXNecromancerSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXNecromancerDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].IdleSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].IdleSelectedSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSprite.SpecialFrameTime = 2000
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSpriteOverlay.SpecialFrameTime = 2000
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].SelectedSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].SelectedSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].SelectedSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].SelectedSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroPaladin] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectPaladinUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectPaladinUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecPaladinForwardWalk, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecPaladinForwardWalkOverlay, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecPaladinSelected, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelecPaladinBackWalk, d2enum.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{490, 210}, Max: image.Point{65, 180}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXPaladinSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXPaladinDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].IdleSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].IdleSelectedSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSprite.SpecialFrameTime = 3400
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSpriteOverlay.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSpriteOverlay.SpecialFrameTime = 3400
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].SelectedSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.SpecialFrameTime = 1300
|
||||
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroAmazon] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectAmazonUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectAmazonUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelecAmazonForwardWalk, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelecAmazonSelected, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelecAmazonBackWalk, d2enum.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{70, 220}, Max: image.Point{55, 200}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXAmazonSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXAmazonDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].IdleSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].IdleSelectedSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].ForwardWalkSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].ForwardWalkSprite.SpecialFrameTime = 2200
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].SelectedSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroAssassin] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectAssassinUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectAssassinUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectAssassinForwardWalk, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelectAssassinSelected, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelectAssassinBackWalk, d2enum.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{175, 235}, Max: image.Point{50, 180}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXAssassinSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXAssassinDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].IdleSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].IdleSelectedSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].ForwardWalkSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].ForwardWalkSprite.SpecialFrameTime = 3800
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].SelectedSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[d2enum.HeroDruid] = &HeroRenderInfo{
|
||||
d2enum.HeroStanceIdle,
|
||||
v.loadSprite(d2common.CharacterSelectDruidUnselected, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectDruidUnselectedH, d2enum.Fechar),
|
||||
v.loadSprite(d2common.CharacterSelectDruidForwardWalk, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelectDruidSelected, d2enum.Fechar),
|
||||
nil,
|
||||
v.loadSprite(d2common.CharacterSelectDruidBackWalk, d2enum.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{680, 220}, Max: image.Point{70, 195}},
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXDruidSelect),
|
||||
v.soundManager.LoadSoundEffect(d2common.SFXDruidDeselect),
|
||||
}
|
||||
v.heroRenderInfo[d2enum.HeroDruid].IdleSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[d2enum.HeroDruid].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].IdleSelectedSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[d2enum.HeroDruid].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].ForwardWalkSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[d2enum.HeroDruid].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].ForwardWalkSprite.SpecialFrameTime = 4800
|
||||
v.heroRenderInfo[d2enum.HeroDruid].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].SelectedSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[d2enum.HeroDruid].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Unload() {
|
||||
v.heroRenderInfo = nil
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) onExitButtonClicked() {
|
||||
v.sceneProvider.SetNextScene(CreateCharacterSelect(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Render(screen *ebiten.Image) {
|
||||
v.bgImage.DrawSegments(screen, 4, 3, 0)
|
||||
v.headingLabel.Draw(screen)
|
||||
if v.selectedHero != d2enum.HeroNone {
|
||||
v.heroClassLabel.Draw(screen)
|
||||
v.heroDesc1Label.Draw(screen)
|
||||
v.heroDesc2Label.Draw(screen)
|
||||
v.heroDesc3Label.Draw(screen)
|
||||
}
|
||||
for heroClass, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance == d2enum.HeroStanceIdle || heroInfo.Stance == d2enum.HeroStanceIdleSelected {
|
||||
v.renderHero(screen, heroClass)
|
||||
}
|
||||
}
|
||||
for heroClass, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance != d2enum.HeroStanceIdle && heroInfo.Stance != d2enum.HeroStanceIdleSelected {
|
||||
v.renderHero(screen, heroClass)
|
||||
}
|
||||
}
|
||||
v.campfire.Draw(screen)
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Update(tickTime float64) {
|
||||
canSelect := true
|
||||
for _, info := range v.heroRenderInfo {
|
||||
if info.Stance != d2enum.HeroStanceIdle && info.Stance != d2enum.HeroStanceIdleSelected && info.Stance != d2enum.HeroStanceSelected {
|
||||
canSelect = false
|
||||
break
|
||||
}
|
||||
}
|
||||
allIdle := true
|
||||
for heroType, data := range v.heroRenderInfo {
|
||||
if allIdle && data.Stance != d2enum.HeroStanceIdle {
|
||||
allIdle = false
|
||||
}
|
||||
v.updateHeroSelectionHover(heroType, canSelect)
|
||||
}
|
||||
if v.selectedHero != d2enum.HeroNone && allIdle {
|
||||
v.selectedHero = d2enum.HeroNone
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) updateHeroSelectionHover(hero d2enum.Hero, canSelect bool) {
|
||||
renderInfo := v.heroRenderInfo[hero]
|
||||
switch renderInfo.Stance {
|
||||
case d2enum.HeroStanceApproaching:
|
||||
if renderInfo.ForwardWalkSprite.OnLastFrame() {
|
||||
renderInfo.Stance = d2enum.HeroStanceSelected
|
||||
renderInfo.SelectedSprite.ResetAnimation()
|
||||
if renderInfo.SelectedSpriteOverlay != nil {
|
||||
renderInfo.SelectedSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
}
|
||||
return
|
||||
case d2enum.HeroStanceRetreating:
|
||||
if renderInfo.BackWalkSprite.OnLastFrame() {
|
||||
renderInfo.Stance = d2enum.HeroStanceIdle
|
||||
renderInfo.IdleSprite.ResetAnimation()
|
||||
}
|
||||
return
|
||||
}
|
||||
if !canSelect {
|
||||
return
|
||||
}
|
||||
if renderInfo.Stance == d2enum.HeroStanceSelected {
|
||||
return
|
||||
}
|
||||
mouseX := v.uiManager.CursorX
|
||||
mouseY := v.uiManager.CursorY
|
||||
b := renderInfo.SelectionBounds
|
||||
mouseHover := (mouseX >= b.Min.X) && (mouseX <= b.Min.X+b.Max.X) && (mouseY >= b.Min.Y) && (mouseY <= b.Min.Y+b.Max.Y)
|
||||
if mouseHover && v.uiManager.CursorButtonPressed(ui.CursorButtonLeft) {
|
||||
// showEntryUi = true;
|
||||
renderInfo.Stance = d2enum.HeroStanceApproaching
|
||||
renderInfo.ForwardWalkSprite.ResetAnimation()
|
||||
if renderInfo.ForwardWalkSpriteOverlay != nil {
|
||||
renderInfo.ForwardWalkSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
for _, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance != d2enum.HeroStanceSelected {
|
||||
continue
|
||||
}
|
||||
heroInfo.SelectSfx.Stop()
|
||||
heroInfo.DeselectSfx.Play()
|
||||
heroInfo.Stance = d2enum.HeroStanceRetreating
|
||||
heroInfo.BackWalkSprite.ResetAnimation()
|
||||
if heroInfo.BackWalkSpriteOverlay != nil {
|
||||
heroInfo.BackWalkSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
}
|
||||
v.selectedHero = hero
|
||||
v.updateHeroText()
|
||||
renderInfo.SelectSfx.Play()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if mouseHover {
|
||||
renderInfo.Stance = d2enum.HeroStanceIdleSelected
|
||||
} else {
|
||||
renderInfo.Stance = d2enum.HeroStanceIdle
|
||||
}
|
||||
|
||||
if v.selectedHero == d2enum.HeroNone && mouseHover {
|
||||
v.selectedHero = hero
|
||||
v.updateHeroText()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) renderHero(screen *ebiten.Image, hero d2enum.Hero) {
|
||||
renderInfo := v.heroRenderInfo[hero]
|
||||
switch renderInfo.Stance {
|
||||
case d2enum.HeroStanceIdle:
|
||||
renderInfo.IdleSprite.Draw(screen)
|
||||
case d2enum.HeroStanceIdleSelected:
|
||||
renderInfo.IdleSelectedSprite.Draw(screen)
|
||||
case d2enum.HeroStanceApproaching:
|
||||
renderInfo.ForwardWalkSprite.Draw(screen)
|
||||
if renderInfo.ForwardWalkSpriteOverlay != nil {
|
||||
renderInfo.ForwardWalkSpriteOverlay.Draw(screen)
|
||||
}
|
||||
case d2enum.HeroStanceSelected:
|
||||
renderInfo.SelectedSprite.Draw(screen)
|
||||
if renderInfo.SelectedSpriteOverlay != nil {
|
||||
renderInfo.SelectedSpriteOverlay.Draw(screen)
|
||||
}
|
||||
case d2enum.HeroStanceRetreating:
|
||||
renderInfo.BackWalkSprite.Draw(screen)
|
||||
if renderInfo.BackWalkSpriteOverlay != nil {
|
||||
renderInfo.BackWalkSpriteOverlay.Draw(screen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) updateHeroText() {
|
||||
switch v.selectedHero {
|
||||
case d2enum.HeroNone:
|
||||
return
|
||||
case d2enum.HeroBarbarian:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharbar"))
|
||||
v.setDescLabels("#1709")
|
||||
case d2enum.HeroNecromancer:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharnec"))
|
||||
v.setDescLabels("#1704")
|
||||
case d2enum.HeroPaladin:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharpal"))
|
||||
v.setDescLabels("#1711")
|
||||
case d2enum.HeroAssassin:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharass"))
|
||||
v.setDescLabels("#305")
|
||||
case d2enum.HeroSorceress:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharsor"))
|
||||
v.setDescLabels("#1710")
|
||||
case d2enum.HeroAmazon:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partycharama"))
|
||||
v.setDescLabels("#1698")
|
||||
case d2enum.HeroDruid:
|
||||
v.heroClassLabel.SetText(d2common.TranslateString("partychardru"))
|
||||
v.setDescLabels("#304")
|
||||
}
|
||||
/*
|
||||
if (selectedHero == null)
|
||||
return;
|
||||
|
||||
switch (selectedHero.Value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
heroClassLabel.Location = new Point(400 - (heroClassLabel.TextArea.Width / 2), 65);
|
||||
heroDesc1Label.Location = new Point(400 - (heroDesc1Label.TextArea.Width / 2), 100);
|
||||
heroDesc2Label.Location = new Point(400 - (heroDesc2Label.TextArea.Width / 2), 115);
|
||||
heroDesc3Label.Location = new Point(400 - (heroDesc3Label.TextArea.Width / 2), 130);
|
||||
*/
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) setDescLabels(descKey string) {
|
||||
heroDesc := d2common.TranslateString(descKey)
|
||||
parts := dh.SplitIntoLinesWithMaxWidth(heroDesc, 37)
|
||||
if len(parts) > 1 {
|
||||
v.heroDesc1Label.SetText(parts[0])
|
||||
} else {
|
||||
v.heroDesc1Label.SetText("")
|
||||
}
|
||||
if len(parts) > 1 {
|
||||
v.heroDesc2Label.SetText(parts[1])
|
||||
} else {
|
||||
v.heroDesc2Label.SetText("")
|
||||
}
|
||||
if len(parts) > 2 {
|
||||
v.heroDesc3Label.SetText(parts[2])
|
||||
} else {
|
||||
v.heroDesc3Label.SetText("")
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
package common
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
// AnimationDataRecord represents a single entry in the animation data dictionary file
|
||||
@ -23,10 +25,10 @@ type AnimationDataRecord struct {
|
||||
var AnimationData map[string][]*AnimationDataRecord
|
||||
|
||||
// LoadAnimationData loads the animation data table into the global AnimationData dictionary
|
||||
func LoadAnimationData(fileProvider FileProvider) {
|
||||
func LoadAnimationData(fileProvider d2interface.FileProvider) {
|
||||
AnimationData = make(map[string][]*AnimationDataRecord)
|
||||
rawData := fileProvider.LoadFile(resourcepaths.AnimationData)
|
||||
streamReader := CreateStreamReader(rawData)
|
||||
rawData := fileProvider.LoadFile(d2common.AnimationData)
|
||||
streamReader := d2common.CreateStreamReader(rawData)
|
||||
for !streamReader.Eof() {
|
||||
dataCount := int(streamReader.GetInt32())
|
||||
for i := 0; i < dataCount; i++ {
|
71
d2data/COF.go
Normal file
71
d2data/COF.go
Normal file
@ -0,0 +1,71 @@
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
type CofLayer struct {
|
||||
Type d2enum.CompositeType
|
||||
Shadow byte
|
||||
Transparent bool
|
||||
DrawEffect d2enum.DrawEffect
|
||||
WeaponClass d2enum.WeaponClass
|
||||
}
|
||||
|
||||
type Cof struct {
|
||||
NumberOfDirections int
|
||||
FramesPerDirection int
|
||||
NumberOfLayers int
|
||||
CofLayers []*CofLayer
|
||||
CompositeLayers map[d2enum.CompositeType]int
|
||||
AnimationFrames []d2enum.AnimationFrame
|
||||
Priority [][][]d2enum.CompositeType
|
||||
}
|
||||
|
||||
func LoadCof(fileName string, fileProvider d2interface.FileProvider) *Cof {
|
||||
result := &Cof{}
|
||||
fileData := fileProvider.LoadFile(fileName)
|
||||
streamReader := d2common.CreateStreamReader(fileData)
|
||||
result.NumberOfLayers = int(streamReader.GetByte())
|
||||
result.FramesPerDirection = int(streamReader.GetByte())
|
||||
result.NumberOfDirections = int(streamReader.GetByte())
|
||||
streamReader.SkipBytes(25) // Skip 25 unknown bytes...
|
||||
result.CofLayers = make([]*CofLayer, 0)
|
||||
result.CompositeLayers = make(map[d2enum.CompositeType]int, 0)
|
||||
for i := 0; i < result.NumberOfLayers; i++ {
|
||||
layer := &CofLayer{}
|
||||
layer.Type = d2enum.CompositeType(streamReader.GetByte())
|
||||
layer.Shadow = streamReader.GetByte()
|
||||
streamReader.SkipBytes(1) // Unknown
|
||||
layer.Transparent = streamReader.GetByte() != 0
|
||||
layer.DrawEffect = d2enum.DrawEffect(streamReader.GetByte())
|
||||
weaponClassStr, _ := streamReader.ReadBytes(4)
|
||||
layer.WeaponClass = d2enum.WeaponClassFromString(strings.TrimSpace(strings.ReplaceAll(string(weaponClassStr), string(0), "")))
|
||||
result.CofLayers = append(result.CofLayers, layer)
|
||||
result.CompositeLayers[layer.Type] = i
|
||||
}
|
||||
animationFrameBytes, _ := streamReader.ReadBytes(result.FramesPerDirection)
|
||||
result.AnimationFrames = make([]d2enum.AnimationFrame, result.FramesPerDirection)
|
||||
for i := range animationFrameBytes {
|
||||
result.AnimationFrames[i] = d2enum.AnimationFrame(animationFrameBytes[i])
|
||||
}
|
||||
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
||||
result.Priority = make([][][]d2enum.CompositeType, result.NumberOfDirections)
|
||||
priorityBytes, _ := streamReader.ReadBytes(priorityLen)
|
||||
for direction := 0; direction < result.NumberOfDirections; direction++ {
|
||||
result.Priority[direction] = make([][]d2enum.CompositeType, result.FramesPerDirection)
|
||||
for frame := 0; frame < result.FramesPerDirection; frame++ {
|
||||
result.Priority[direction][frame] = make([]d2enum.CompositeType, result.NumberOfLayers)
|
||||
for i := 0; i < result.NumberOfLayers; i++ {
|
||||
result.Priority[direction][frame][i] = d2enum.CompositeType(priorityBytes[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
package common
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
type DCCPixelBufferEntry struct {
|
||||
@ -29,7 +35,7 @@ type DCCDirectionFrame struct {
|
||||
NumberOfOptionalBytes int
|
||||
NumberOfCodedBytes int
|
||||
FrameIsBottomUp bool
|
||||
Box Rectangle
|
||||
Box d2common.Rectangle
|
||||
Cells []DCCCell
|
||||
PixelData []byte
|
||||
HorizontalCellCount int
|
||||
@ -52,7 +58,7 @@ type DCCDirection struct {
|
||||
RawPixelCodesBitstreamSize int
|
||||
Frames []*DCCDirectionFrame
|
||||
PaletteEntries [256]byte
|
||||
Box Rectangle
|
||||
Box d2common.Rectangle
|
||||
Cells []*DCCCell
|
||||
PixelData []byte
|
||||
HorizontalCellCount int
|
||||
@ -76,7 +82,7 @@ var dccDir16 = []byte{4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14, 3, 15}
|
||||
var dccDir32 = []byte{4, 16, 8, 17, 0, 18, 9, 19, 5, 20, 10, 21, 1, 22, 11, 23,
|
||||
6, 24, 12, 25, 2, 26, 13, 27, 7, 28, 14, 29, 3, 30, 15, 31}
|
||||
|
||||
func CreateDCCDirectionFrame(bits *BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
||||
func CreateDCCDirectionFrame(bits *d2common.BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
||||
result := &DCCDirectionFrame{}
|
||||
bits.GetBits(direction.Variable0Bits) // Variable0
|
||||
result.Width = int(bits.GetBits(direction.WidthBits))
|
||||
@ -89,7 +95,7 @@ func CreateDCCDirectionFrame(bits *BitMuncher, direction *DCCDirection) *DCCDire
|
||||
if result.FrameIsBottomUp {
|
||||
log.Panic("Bottom up frames are not implemented.")
|
||||
} else {
|
||||
result.Box = Rectangle{
|
||||
result.Box = d2common.Rectangle{
|
||||
result.XOffset,
|
||||
result.YOffset - result.Height + 1,
|
||||
result.Width,
|
||||
@ -160,7 +166,7 @@ func (v *DCCDirectionFrame) CalculateCells(direction *DCCDirection) {
|
||||
}
|
||||
}
|
||||
|
||||
func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
||||
func CreateDCCDirection(bm *d2common.BitMuncher, file *DCC) *DCCDirection {
|
||||
result := &DCCDirection{}
|
||||
result.OutSizeCoded = int(bm.GetUInt32())
|
||||
result.CompressionFlags = int(bm.GetBits(2))
|
||||
@ -179,12 +185,12 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
||||
// Load the frame headers
|
||||
for frameIdx := 0; frameIdx < file.FramesPerDirection; frameIdx++ {
|
||||
result.Frames[frameIdx] = CreateDCCDirectionFrame(bm, result)
|
||||
minx = int(MinInt32(int32(result.Frames[frameIdx].Box.Left), int32(minx)))
|
||||
miny = int(MinInt32(int32(result.Frames[frameIdx].Box.Top), int32(miny)))
|
||||
maxx = int(MaxInt32(int32(result.Frames[frameIdx].Box.Right()), int32(maxx)))
|
||||
maxy = int(MaxInt32(int32(result.Frames[frameIdx].Box.Bottom()), int32(maxy)))
|
||||
minx = int(d2helper.MinInt32(int32(result.Frames[frameIdx].Box.Left), int32(minx)))
|
||||
miny = int(d2helper.MinInt32(int32(result.Frames[frameIdx].Box.Top), int32(miny)))
|
||||
maxx = int(d2helper.MaxInt32(int32(result.Frames[frameIdx].Box.Right()), int32(maxx)))
|
||||
maxy = int(d2helper.MaxInt32(int32(result.Frames[frameIdx].Box.Bottom()), int32(maxy)))
|
||||
}
|
||||
result.Box = Rectangle{minx, miny, (maxx - minx), (maxy - miny)}
|
||||
result.Box = d2common.Rectangle{minx, miny, (maxx - minx), (maxy - miny)}
|
||||
if result.OptionalDataBits > 0 {
|
||||
log.Panic("Optional bits in DCC data is not currently supported.")
|
||||
}
|
||||
@ -210,15 +216,15 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
||||
// here. For example, if you are on byte offset 3, bit offset 6, and
|
||||
// the EqualCellsBitstreamSize is 20 bytes, then the next bit stream
|
||||
// will be located at byte 23, bit offset 6!
|
||||
equalCellsBitstream := CopyBitMuncher(bm)
|
||||
equalCellsBitstream := d2common.CopyBitMuncher(bm)
|
||||
bm.SkipBits(result.EqualCellsBitstreamSize)
|
||||
pixelMaskBitstream := CopyBitMuncher(bm)
|
||||
pixelMaskBitstream := d2common.CopyBitMuncher(bm)
|
||||
bm.SkipBits(result.PixelMaskBitstreamSize)
|
||||
encodingTypeBitsream := CopyBitMuncher(bm)
|
||||
encodingTypeBitsream := d2common.CopyBitMuncher(bm)
|
||||
bm.SkipBits(result.EncodingTypeBitsreamSize)
|
||||
rawPixelCodesBitstream := CopyBitMuncher(bm)
|
||||
rawPixelCodesBitstream := d2common.CopyBitMuncher(bm)
|
||||
bm.SkipBits(result.RawPixelCodesBitstreamSize)
|
||||
pixelCodeandDisplacement := CopyBitMuncher(bm)
|
||||
pixelCodeandDisplacement := d2common.CopyBitMuncher(bm)
|
||||
// Calculate the cells for the direction
|
||||
result.CalculateCells()
|
||||
// Calculate the cells for each of the frames
|
||||
@ -247,7 +253,7 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *DCCDirection) GenerateFrames(pcd *BitMuncher) {
|
||||
func (v *DCCDirection) GenerateFrames(pcd *d2common.BitMuncher) {
|
||||
pbIdx := 0
|
||||
for _, cell := range v.Cells {
|
||||
cell.LastWidth = -1
|
||||
@ -339,7 +345,7 @@ func (v *DCCDirection) GenerateFrames(pcd *BitMuncher) {
|
||||
v.PixelBuffer = nil
|
||||
}
|
||||
|
||||
func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
||||
func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *d2common.BitMuncher) {
|
||||
lastPixel := uint32(0)
|
||||
maxCellX := 0
|
||||
maxCellY := 0
|
||||
@ -493,10 +499,10 @@ func (v *DCCDirection) CalculateCells() {
|
||||
}
|
||||
}
|
||||
|
||||
func LoadDCC(path string, fileProvider FileProvider) *DCC {
|
||||
func LoadDCC(path string, fileProvider d2interface.FileProvider) *DCC {
|
||||
result := &DCC{}
|
||||
fileData := fileProvider.LoadFile(path)
|
||||
var bm = CreateBitMuncher(fileData, 0)
|
||||
var bm = d2common.CreateBitMuncher(fileData, 0)
|
||||
result.Signature = int(bm.GetByte())
|
||||
if result.Signature != 0x74 {
|
||||
log.Fatal("Signature expected to be 0x74 but it is not.")
|
||||
@ -527,7 +533,7 @@ func LoadDCC(path string, fileProvider FileProvider) *DCC {
|
||||
case 32:
|
||||
dir = dccDir32[i]
|
||||
}
|
||||
result.Directions[dir] = CreateDCCDirection(CreateBitMuncher(fileData, directionOffsets[i]*8), result)
|
||||
result.Directions[dir] = CreateDCCDirection(d2common.CreateBitMuncher(fileData, directionOffsets[i]*8), result)
|
||||
}
|
||||
|
||||
return result
|
@ -1,7 +1,10 @@
|
||||
package _map
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
var dirLookup = []int32{
|
||||
@ -67,23 +70,23 @@ type SubstitutionGroup struct {
|
||||
}
|
||||
|
||||
type DS1 struct {
|
||||
Version int32 // The version of the DS1
|
||||
Width int32 // Width of map, in # of tiles
|
||||
Height int32 // Height of map, in # of tiles
|
||||
Act int32 // Act, from 1 to 5. This tells which act table to use for the Objects list
|
||||
SubstitutionType int32 // SubstitutionType (layer type): 0 if no layer, else type 1 or type 2
|
||||
Files []string // FilePtr table of file string pointers
|
||||
NumberOfWalls int32 // WallNum number of wall & orientation layers used
|
||||
NumberOfFloors int32 // number of floor layers used
|
||||
NumberOfShadowLayers int32 // ShadowNum number of shadow layer used
|
||||
NumberOfSubstitutionLayers int32 // SubstitutionNum number of substitution layer used
|
||||
SubstitutionGroupsNum int32 // SubstitutionGroupsNum number of substitution groups, datas between objects & NPC paths
|
||||
Objects []common.Object // Objects
|
||||
Version int32 // The version of the DS1
|
||||
Width int32 // Width of map, in # of tiles
|
||||
Height int32 // Height of map, in # of tiles
|
||||
Act int32 // Act, from 1 to 5. This tells which act table to use for the Objects list
|
||||
SubstitutionType int32 // SubstitutionType (layer type): 0 if no layer, else type 1 or type 2
|
||||
Files []string // FilePtr table of file string pointers
|
||||
NumberOfWalls int32 // WallNum number of wall & orientation layers used
|
||||
NumberOfFloors int32 // number of floor layers used
|
||||
NumberOfShadowLayers int32 // ShadowNum number of shadow layer used
|
||||
NumberOfSubstitutionLayers int32 // SubstitutionNum number of substitution layer used
|
||||
SubstitutionGroupsNum int32 // SubstitutionGroupsNum number of substitution groups, datas between objects & NPC paths
|
||||
Objects []Object // Objects
|
||||
Tiles [][]TileRecord
|
||||
SubstitutionGroups []SubstitutionGroup
|
||||
}
|
||||
|
||||
func LoadDS1(path string, fileProvider common.FileProvider) *DS1 {
|
||||
func LoadDS1(path string, fileProvider d2interface.FileProvider) *DS1 {
|
||||
ds1 := &DS1{
|
||||
NumberOfFloors: 1,
|
||||
NumberOfWalls: 1,
|
||||
@ -91,12 +94,12 @@ func LoadDS1(path string, fileProvider common.FileProvider) *DS1 {
|
||||
NumberOfSubstitutionLayers: 0,
|
||||
}
|
||||
fileData := fileProvider.LoadFile(path)
|
||||
br := common.CreateStreamReader(fileData)
|
||||
br := d2common.CreateStreamReader(fileData)
|
||||
ds1.Version = br.GetInt32()
|
||||
ds1.Width = br.GetInt32() + 1
|
||||
ds1.Height = br.GetInt32() + 1
|
||||
if ds1.Version >= 8 {
|
||||
ds1.Act = common.MinInt32(5, br.GetInt32()+1)
|
||||
ds1.Act = d2helper.MinInt32(5, br.GetInt32()+1)
|
||||
}
|
||||
if ds1.Version >= 10 {
|
||||
ds1.SubstitutionType = br.GetInt32()
|
||||
@ -224,19 +227,19 @@ func LoadDS1(path string, fileProvider common.FileProvider) *DS1 {
|
||||
}
|
||||
}
|
||||
}
|
||||
ds1.Objects = make([]common.Object, 0)
|
||||
ds1.Objects = make([]Object, 0)
|
||||
if ds1.Version >= 2 {
|
||||
numberOfObjects := br.GetInt32()
|
||||
for objIdx := 0; objIdx < int(numberOfObjects); objIdx++ {
|
||||
newObject := common.Object{}
|
||||
newObject := Object{}
|
||||
newObject.Type = br.GetInt32()
|
||||
newObject.Id = br.GetInt32()
|
||||
newObject.X = br.GetInt32()
|
||||
newObject.Y = br.GetInt32()
|
||||
newObject.Flags = br.GetInt32()
|
||||
newObject.Lookup = common.LookupObject(int(ds1.Act), int(newObject.Type), int(newObject.Id))
|
||||
newObject.Lookup = datadict.LookupObject(int(ds1.Act), int(newObject.Type), int(newObject.Id))
|
||||
if newObject.Lookup != nil && newObject.Lookup.ObjectsTxtId != -1 {
|
||||
newObject.ObjectInfo = common.Objects[newObject.Lookup.ObjectsTxtId]
|
||||
newObject.ObjectInfo = datadict.Objects[newObject.Lookup.ObjectsTxtId]
|
||||
}
|
||||
ds1.Objects = append(ds1.Objects, newObject)
|
||||
}
|
||||
@ -273,10 +276,10 @@ func LoadDS1(path string, fileProvider common.FileProvider) *DS1 {
|
||||
}
|
||||
if objIdx > -1 {
|
||||
if ds1.Objects[objIdx].Paths == nil {
|
||||
ds1.Objects[objIdx].Paths = make([]common.Path, numPaths)
|
||||
ds1.Objects[objIdx].Paths = make([]d2common.Path, numPaths)
|
||||
}
|
||||
for pathIdx := 0; pathIdx < int(numPaths); pathIdx++ {
|
||||
newPath := common.Path{}
|
||||
newPath := d2common.Path{}
|
||||
newPath.X = br.GetInt32()
|
||||
newPath.Y = br.GetInt32()
|
||||
if ds1.Version >= 15 {
|
@ -1,9 +1,11 @@
|
||||
package _map
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
// https://d2mods.info/forum/viewtopic.php?t=65163
|
||||
@ -47,10 +49,10 @@ const (
|
||||
BlockFormatIsometric BlockDataFormat = 1
|
||||
)
|
||||
|
||||
func LoadDT1(path string, fileProvider common.FileProvider) *DT1 {
|
||||
func LoadDT1(path string, fileProvider d2interface.FileProvider) *DT1 {
|
||||
result := &DT1{}
|
||||
fileData := fileProvider.LoadFile(path)
|
||||
br := common.CreateStreamReader(fileData)
|
||||
br := d2common.CreateStreamReader(fileData)
|
||||
ver1 := br.GetInt32()
|
||||
ver2 := br.GetInt32()
|
||||
if ver1 != 7 || ver2 != 6 {
|
17
d2data/Object.go
Normal file
17
d2data/Object.go
Normal file
@ -0,0 +1,17 @@
|
||||
package d2data
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
Type int32
|
||||
Id int32
|
||||
X int32
|
||||
Y int32
|
||||
Flags int32
|
||||
Paths []d2common.Path
|
||||
Lookup *datadict.ObjectLookupRecord
|
||||
ObjectInfo *datadict.ObjectRecord
|
||||
}
|
@ -32,7 +32,7 @@ package compression
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
// linkedNode is a node which is both hierachcical (parent/child) and doubly linked (next/prev)
|
||||
@ -182,7 +182,7 @@ var sPrime = [][]byte{
|
||||
},
|
||||
}
|
||||
|
||||
func decode(input *common.BitStream, head *linkedNode) *linkedNode {
|
||||
func decode(input *d2common.BitStream, head *linkedNode) *linkedNode {
|
||||
node := head
|
||||
|
||||
for node.Child0 != nil {
|
||||
@ -344,8 +344,8 @@ func HuffmanDecompress(data []byte) []byte {
|
||||
tail := buildList(sPrime[comptype])
|
||||
head := buildTree(tail)
|
||||
|
||||
outputstream := common.CreateStreamWriter()
|
||||
bitstream := common.CreateBitStream(data[1:])
|
||||
outputstream := d2common.CreateStreamWriter()
|
||||
bitstream := d2common.CreateBitStream(data[1:])
|
||||
var decoded int
|
||||
for true {
|
||||
node := decode(bitstream, head)
|
@ -1,7 +1,7 @@
|
||||
package compression
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
var sLookup = []int{
|
||||
@ -30,8 +30,8 @@ func WavDecompress(data []byte, channelCount int) []byte {
|
||||
Array1 := []int{0x2c, 0x2c}
|
||||
Array2 := make([]int, channelCount)
|
||||
|
||||
input := common.CreateStreamReader(data)
|
||||
output := common.CreateStreamWriter()
|
||||
input := d2common.CreateStreamReader(data)
|
||||
output := d2common.CreateStreamWriter()
|
||||
input.GetByte()
|
||||
|
||||
shift := input.GetByte()
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type ArmorRecord struct {
|
||||
@ -135,28 +139,28 @@ func createArmorRecord(line string) ArmorRecord {
|
||||
result := ArmorRecord{
|
||||
Name: r[inc()],
|
||||
|
||||
Version: StringToInt(EmptyToZero(r[inc()])),
|
||||
CompactSave: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Rarity: StringToInt(EmptyToZero(r[inc()])),
|
||||
Spawnable: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
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: StringToInt(EmptyToZero(r[inc()])),
|
||||
MaxAC: StringToInt(EmptyToZero(r[inc()])),
|
||||
Absorbs: StringToInt(EmptyToZero(r[inc()])),
|
||||
Speed: StringToInt(EmptyToZero(r[inc()])),
|
||||
RequiredStrength: StringToInt(EmptyToZero(r[inc()])),
|
||||
Block: StringToInt(EmptyToZero(r[inc()])),
|
||||
Durability: StringToInt(EmptyToZero(r[inc()])),
|
||||
NoDurability: StringToInt(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: StringToInt(EmptyToZero(r[inc()])),
|
||||
RequiredLevel: StringToInt(EmptyToZero(r[inc()])),
|
||||
Cost: StringToInt(EmptyToZero(r[inc()])),
|
||||
GambleCost: StringToInt(EmptyToZero(r[inc()])),
|
||||
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: StringToInt(EmptyToZero(r[inc()])),
|
||||
AutoPrefix: StringToInt(EmptyToZero(r[inc()])),
|
||||
MagicLevel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
AutoPrefix: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
AlternateGfx: r[inc()],
|
||||
OpenBetaGfx: r[inc()],
|
||||
@ -164,77 +168,77 @@ func createArmorRecord(line string) ArmorRecord {
|
||||
UberCode: r[inc()],
|
||||
UltraCode: r[inc()],
|
||||
|
||||
SpellOffset: StringToInt(EmptyToZero(r[inc()])),
|
||||
SpellOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
Component: StringToInt(EmptyToZero(r[inc()])),
|
||||
InventoryWidth: StringToInt(EmptyToZero(r[inc()])),
|
||||
InventoryHeight: StringToInt(EmptyToZero(r[inc()])),
|
||||
HasInventory: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
GemSockets: StringToInt(EmptyToZero(r[inc()])),
|
||||
GemApplyType: StringToInt(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: StringToInt(EmptyToZero(r[inc()])),
|
||||
AnimLeftArm: StringToInt(EmptyToZero(r[inc()])),
|
||||
AnimTorso: StringToInt(EmptyToZero(r[inc()])),
|
||||
AnimLegs: StringToInt(EmptyToZero(r[inc()])),
|
||||
AnimRightShoulderPad: StringToInt(EmptyToZero(r[inc()])),
|
||||
AnimLeftShoulderPad: StringToInt(EmptyToZero(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: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Useable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
Throwable: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Stackable: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
MinStack: StringToInt(EmptyToZero(r[inc()])),
|
||||
MaxStack: StringToInt(EmptyToZero(r[inc()])),
|
||||
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: StringToInt(EmptyToZero(r[inc()])),
|
||||
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
UseSound: r[inc()],
|
||||
|
||||
Unique: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Transparent: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
TransTable: StringToInt(EmptyToZero(r[inc()])),
|
||||
Quivered: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
LightRadius: StringToInt(EmptyToZero(r[inc()])),
|
||||
Belt: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
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: StringToInt(EmptyToZero(r[inc()])),
|
||||
Quest: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
MissileType: StringToInt(EmptyToZero(r[inc()])),
|
||||
DurabilityWarning: StringToInt(EmptyToZero(r[inc()])),
|
||||
QuantityWarning: StringToInt(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: StringToInt(EmptyToZero(r[inc()])),
|
||||
MaxDamage: StringToInt(EmptyToZero(r[inc()])),
|
||||
StrengthBonus: StringToInt(EmptyToZero(r[inc()])),
|
||||
DexterityBonus: StringToInt(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: StringToInt(EmptyToZero(r[inc()])),
|
||||
BitField1: StringToInt(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: StringToInt(EmptyToZero(r[inc()])),
|
||||
InventoryColorTransform: StringToInt(EmptyToZero(r[inc()])),
|
||||
ColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
InventoryColorTransform: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
SkipName: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
SkipName: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
NightmareUpgrade: r[inc()],
|
||||
HellUpgrade: r[inc()],
|
||||
|
||||
UnusedMinDamage: StringToInt(EmptyToZero(r[inc()])),
|
||||
UnusedMaxDamage: StringToInt(EmptyToZero(r[inc()])),
|
||||
UnusedMinDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
UnusedMaxDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
Nameable: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Nameable: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -264,9 +268,9 @@ func createArmorVendorParams(r *[]string, inc func() int) map[string]*ItemVendor
|
||||
|
||||
var Armors map[string]*ArmorRecord
|
||||
|
||||
func LoadArmors(fileProvider FileProvider) {
|
||||
func LoadArmors(fileProvider d2interface.FileProvider) {
|
||||
Armors = make(map[string]*ArmorRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.Armor)), "\r\n")[1:]
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.Armor)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type LevelPresetRecord struct {
|
||||
@ -39,21 +43,21 @@ func createLevelPresetRecord(props []string) LevelPresetRecord {
|
||||
}
|
||||
result := LevelPresetRecord{
|
||||
Name: props[inc()],
|
||||
DefinitionId: StringToInt(props[inc()]),
|
||||
LevelId: StringToInt(props[inc()]),
|
||||
Populate: StringToUint8(props[inc()]) == 1,
|
||||
Logicals: StringToUint8(props[inc()]) == 1,
|
||||
Outdoors: StringToUint8(props[inc()]) == 1,
|
||||
Animate: StringToUint8(props[inc()]) == 1,
|
||||
KillEdge: StringToUint8(props[inc()]) == 1,
|
||||
FillBlanks: StringToUint8(props[inc()]) == 1,
|
||||
SizeX: StringToInt(props[inc()]),
|
||||
SizeY: StringToInt(props[inc()]),
|
||||
AutoMap: StringToUint8(props[inc()]) == 1,
|
||||
Scan: StringToUint8(props[inc()]) == 1,
|
||||
Pops: StringToInt(props[inc()]),
|
||||
PopPad: StringToInt(props[inc()]),
|
||||
FileCount: StringToInt(props[inc()]),
|
||||
DefinitionId: dh.StringToInt(props[inc()]),
|
||||
LevelId: dh.StringToInt(props[inc()]),
|
||||
Populate: dh.StringToUint8(props[inc()]) == 1,
|
||||
Logicals: dh.StringToUint8(props[inc()]) == 1,
|
||||
Outdoors: dh.StringToUint8(props[inc()]) == 1,
|
||||
Animate: dh.StringToUint8(props[inc()]) == 1,
|
||||
KillEdge: dh.StringToUint8(props[inc()]) == 1,
|
||||
FillBlanks: dh.StringToUint8(props[inc()]) == 1,
|
||||
SizeX: dh.StringToInt(props[inc()]),
|
||||
SizeY: dh.StringToInt(props[inc()]),
|
||||
AutoMap: dh.StringToUint8(props[inc()]) == 1,
|
||||
Scan: dh.StringToUint8(props[inc()]) == 1,
|
||||
Pops: dh.StringToInt(props[inc()]),
|
||||
PopPad: dh.StringToInt(props[inc()]),
|
||||
FileCount: dh.StringToInt(props[inc()]),
|
||||
Files: [6]string{
|
||||
props[inc()],
|
||||
props[inc()],
|
||||
@ -62,18 +66,18 @@ func createLevelPresetRecord(props []string) LevelPresetRecord {
|
||||
props[inc()],
|
||||
props[inc()],
|
||||
},
|
||||
Dt1Mask: StringToUint(props[inc()]),
|
||||
Beta: StringToUint8(props[inc()]) == 1,
|
||||
Expansion: StringToUint8(props[inc()]) == 1,
|
||||
Dt1Mask: dh.StringToUint(props[inc()]),
|
||||
Beta: dh.StringToUint8(props[inc()]) == 1,
|
||||
Expansion: dh.StringToUint8(props[inc()]) == 1,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var LevelPresets map[int]*LevelPresetRecord
|
||||
|
||||
func LoadLevelPresets(fileProvider FileProvider) {
|
||||
func LoadLevelPresets(fileProvider d2interface.FileProvider) {
|
||||
LevelPresets = make(map[int]*LevelPresetRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.LevelPreset)), "\r\n")[1:]
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.LevelPreset)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type LevelTypeRecord struct {
|
||||
@ -18,8 +22,8 @@ type LevelTypeRecord struct {
|
||||
|
||||
var LevelTypes []LevelTypeRecord
|
||||
|
||||
func LoadLevelTypes(fileProvider FileProvider) {
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.LevelType)), "\r\n")[1:]
|
||||
func LoadLevelTypes(fileProvider d2interface.FileProvider) {
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.LevelType)), "\r\n")[1:]
|
||||
LevelTypes = make([]LevelTypeRecord, len(data))
|
||||
for i, line := range data {
|
||||
idx := -1
|
||||
@ -35,7 +39,7 @@ func LoadLevelTypes(fileProvider FileProvider) {
|
||||
continue
|
||||
}
|
||||
LevelTypes[i].Name = parts[inc()]
|
||||
LevelTypes[i].Id = StringToInt(parts[inc()])
|
||||
LevelTypes[i].Id = dh.StringToInt(parts[inc()])
|
||||
for fileIdx := range LevelTypes[i].Files {
|
||||
LevelTypes[i].Files[fileIdx] = parts[inc()]
|
||||
if LevelTypes[i].Files[fileIdx] == "0" {
|
||||
@ -44,7 +48,7 @@ func LoadLevelTypes(fileProvider FileProvider) {
|
||||
|
||||
}
|
||||
LevelTypes[i].Beta = parts[inc()] != "1"
|
||||
LevelTypes[i].Act = StringToInt(parts[inc()])
|
||||
LevelTypes[i].Act = dh.StringToInt(parts[inc()])
|
||||
LevelTypes[i].Expansion = parts[inc()] != "1"
|
||||
}
|
||||
log.Printf("Loaded %d LevelType records", len(LevelTypes))
|
@ -1,9 +1,11 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
type LevelWarpRecord struct {
|
||||
@ -23,10 +25,10 @@ type LevelWarpRecord struct {
|
||||
|
||||
var LevelWarps map[int]*LevelWarpRecord
|
||||
|
||||
func LoadLevelWarps(fileProvider FileProvider) {
|
||||
func LoadLevelWarps(fileProvider d2interface.FileProvider) {
|
||||
LevelWarps = make(map[int]*LevelWarpRecord)
|
||||
levelWarpData := fileProvider.LoadFile(resourcepaths.LevelWarp)
|
||||
streamReader := CreateStreamReader(levelWarpData)
|
||||
levelWarpData := fileProvider.LoadFile(d2common.LevelWarp)
|
||||
streamReader := d2common.CreateStreamReader(levelWarpData)
|
||||
numRecords := int(streamReader.GetInt32())
|
||||
for i := 0; i < numRecords; i++ {
|
||||
id := int(streamReader.GetInt32())
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type MissileCalcParam struct {
|
||||
@ -196,16 +200,16 @@ func createMissileRecord(line string) MissileRecord {
|
||||
return i
|
||||
}
|
||||
// note: in this file, empties are equivalent to zero, so all numerical conversions should
|
||||
// be wrapped in an EmptyToZero transform
|
||||
// be wrapped in an dh.EmptyToZero transform
|
||||
result := MissileRecord{
|
||||
Name: r[inc()],
|
||||
Id: StringToInt(EmptyToZero(r[inc()])),
|
||||
Id: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
ClientMovementFunc: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ClientCollisionFunc: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ServerMovementFunc: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ServerCollisionFunc: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ServerDamageFunc: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ClientMovementFunc: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
ClientCollisionFunc: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
ServerMovementFunc: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
ServerCollisionFunc: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
ServerDamageFunc: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
|
||||
ServerMovementCalc: loadMissileCalc(&r, inc, 5),
|
||||
ClientMovementCalc: loadMissileCalc(&r, inc, 5),
|
||||
@ -213,12 +217,12 @@ func createMissileRecord(line string) MissileRecord {
|
||||
ClientCollisionCalc: loadMissileCalc(&r, inc, 3),
|
||||
ServerDamageCalc: loadMissileCalc(&r, inc, 2),
|
||||
|
||||
Velocity: StringToInt(EmptyToZero(r[inc()])),
|
||||
MaxVelocity: StringToInt(EmptyToZero(r[inc()])),
|
||||
LevelVelocityBonus: StringToInt(EmptyToZero(r[inc()])),
|
||||
Accel: StringToInt(EmptyToZero(r[inc()])),
|
||||
Range: StringToInt(EmptyToZero(r[inc()])),
|
||||
LevelRangeBonus: StringToInt(EmptyToZero(r[inc()])),
|
||||
Velocity: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
MaxVelocity: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
LevelVelocityBonus: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
Accel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
Range: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
LevelRangeBonus: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
Light: loadMissileLight(&r, inc),
|
||||
|
||||
@ -226,54 +230,54 @@ func createMissileRecord(line string) MissileRecord {
|
||||
|
||||
Collision: loadMissileCollision(&r, inc),
|
||||
|
||||
XOffset: StringToInt(EmptyToZero(r[inc()])),
|
||||
YOffset: StringToInt(EmptyToZero(r[inc()])),
|
||||
ZOffset: StringToInt(EmptyToZero(r[inc()])),
|
||||
Size: StringToInt(EmptyToZero(r[inc()])),
|
||||
XOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
YOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
ZOffset: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
Size: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
DestroyedByTP: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
DestroyedByTPFrame: StringToInt(EmptyToZero(r[inc()])),
|
||||
CanDestroy: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
DestroyedByTP: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
DestroyedByTPFrame: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
CanDestroy: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
UseAttackRating: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
AlwaysExplode: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
UseAttackRating: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
AlwaysExplode: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
ClientExplosion: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
TownSafe: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
IgnoreBossModifiers: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
IgnoreMultishot: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
HolyFilterType: StringToInt(EmptyToZero(r[inc()])),
|
||||
CanBeSlowed: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
TriggersHitEvents: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
TriggersGetHit: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
SoftHit: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
KnockbackPercent: StringToInt(EmptyToZero(r[inc()])),
|
||||
ClientExplosion: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
TownSafe: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
IgnoreBossModifiers: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
IgnoreMultishot: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
HolyFilterType: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
CanBeSlowed: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
TriggersHitEvents: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
TriggersGetHit: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
SoftHit: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
KnockbackPercent: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
TransparencyMode: StringToInt(EmptyToZero(r[inc()])),
|
||||
TransparencyMode: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
UseQuantity: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
AffectedByPierce: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
SpecialSetup: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
UseQuantity: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
AffectedByPierce: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
SpecialSetup: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
MissileSkill: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
MissileSkill: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
SkillName: r[inc()],
|
||||
|
||||
ResultFlags: StringToInt(EmptyToZero(r[inc()])),
|
||||
HitFlags: StringToInt(EmptyToZero(r[inc()])),
|
||||
ResultFlags: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
HitFlags: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
HitShift: StringToInt(EmptyToZero(r[inc()])),
|
||||
ApplyMastery: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
SourceDamage: StringToInt(EmptyToZero(r[inc()])),
|
||||
HalfDamageForTwoHander: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
SourceMissDamage: StringToInt(EmptyToZero(r[inc()])),
|
||||
HitShift: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
ApplyMastery: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
SourceDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
HalfDamageForTwoHander: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
SourceMissDamage: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
Damage: loadMissileDamage(&r, inc),
|
||||
ElementalDamage: loadMissileElementalDamage(&r, inc),
|
||||
|
||||
HitClass: StringToInt(EmptyToZero(r[inc()])),
|
||||
NumDirections: StringToInt(EmptyToZero(r[inc()])),
|
||||
LocalBlood: StringToInt(EmptyToZero(r[inc()])),
|
||||
DamageReductionRate: StringToInt(EmptyToZero(r[inc()])),
|
||||
HitClass: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
NumDirections: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
LocalBlood: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
DamageReductionRate: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
TravelSound: r[inc()],
|
||||
HitSound: r[inc()],
|
||||
@ -291,9 +295,9 @@ func createMissileRecord(line string) MissileRecord {
|
||||
|
||||
var Missiles map[int]*MissileRecord
|
||||
|
||||
func LoadMissiles(fileProvider FileProvider) {
|
||||
func LoadMissiles(fileProvider d2interface.FileProvider) {
|
||||
Missiles = make(map[int]*MissileRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.Missiles)), "\r\n")[1:]
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.Missiles)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
@ -306,7 +310,7 @@ func LoadMissiles(fileProvider FileProvider) {
|
||||
|
||||
func loadMissileCalcParam(r *[]string, inc func() int) MissileCalcParam {
|
||||
result := MissileCalcParam{
|
||||
Param: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Param: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
Desc: (*r)[inc()],
|
||||
}
|
||||
return result
|
||||
@ -326,64 +330,64 @@ func loadMissileCalc(r *[]string, inc func() int, params int) MissileCalc {
|
||||
|
||||
func loadMissileLight(r *[]string, inc func() int) MissileLight {
|
||||
result := MissileLight{
|
||||
Diameter: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Flicker: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Red: StringToUint8(EmptyToZero((*r)[inc()])),
|
||||
Green: StringToUint8(EmptyToZero((*r)[inc()])),
|
||||
Blue: StringToUint8(EmptyToZero((*r)[inc()])),
|
||||
Diameter: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
Flicker: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
Red: dh.StringToUint8(dh.EmptyToZero((*r)[inc()])),
|
||||
Green: dh.StringToUint8(dh.EmptyToZero((*r)[inc()])),
|
||||
Blue: dh.StringToUint8(dh.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func loadMissileAnimation(r *[]string, inc func() int) MissileAnimation {
|
||||
result := MissileAnimation{
|
||||
StepsBeforeVisible: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StepsBeforeActive: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
LoopAnimation: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
StepsBeforeVisible: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
StepsBeforeActive: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
LoopAnimation: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
CelFileName: (*r)[inc()],
|
||||
AnimationRate: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
AnimationLength: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
AnimationSpeed: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StartingFrame: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
HasSubLoop: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
SubStartingFrame: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
SubEndingFrame: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
AnimationRate: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
AnimationLength: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
AnimationSpeed: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
StartingFrame: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
HasSubLoop: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
SubStartingFrame: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
SubEndingFrame: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func loadMissileCollision(r *[]string, inc func() int) MissileCollision {
|
||||
result := MissileCollision{
|
||||
CollisionType: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
DestroyedUponCollision: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
FriendlyFire: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
LastCollide: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
Collision: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
ClientCollision: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
ClientSend: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
UseCollisionTimer: StringToInt(EmptyToZero((*r)[inc()])) == 1,
|
||||
TimerFrames: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
CollisionType: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
DestroyedUponCollision: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
FriendlyFire: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
LastCollide: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
Collision: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
ClientCollision: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
ClientSend: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
UseCollisionTimer: dh.StringToInt(dh.EmptyToZero((*r)[inc()])) == 1,
|
||||
TimerFrames: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func loadMissileDamage(r *[]string, inc func() int) MissileDamage {
|
||||
result := MissileDamage{
|
||||
MinDamage: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
MinDamage: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
MinLevelDamage: [5]int{
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
},
|
||||
MaxDamage: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
MaxDamage: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
MaxLevelDamage: [5]int{
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
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()],
|
||||
}
|
||||
@ -394,11 +398,11 @@ func loadMissileElementalDamage(r *[]string, inc func() int) MissileElementalDam
|
||||
result := MissileElementalDamage{
|
||||
ElementType: (*r)[inc()],
|
||||
Damage: loadMissileDamage(r, inc),
|
||||
Duration: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Duration: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
LevelDuration: [3]int{
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
StringToInt(EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
},
|
||||
}
|
||||
return result
|
12
d2data/datadict/MonStats.go
Normal file
12
d2data/datadict/MonStats.go
Normal file
@ -0,0 +1,12 @@
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
var MonStatsDictionary *d2common.DataDictionary
|
||||
|
||||
func LoadMonStats(fileProvider d2interface.FileProvider) {
|
||||
MonStatsDictionary = d2common.LoadDataDictionary(string(fileProvider.LoadFile(d2common.MonStats)))
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
@ -1,10 +1,12 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
type ObjectTypeRecord struct {
|
||||
@ -14,9 +16,9 @@ type ObjectTypeRecord struct {
|
||||
|
||||
var ObjectTypes []ObjectTypeRecord
|
||||
|
||||
func LoadObjectTypes(fileProvider FileProvider) {
|
||||
objectTypeData := fileProvider.LoadFile(resourcepaths.ObjectType)
|
||||
streamReader := CreateStreamReader(objectTypeData)
|
||||
func LoadObjectTypes(fileProvider d2interface.FileProvider) {
|
||||
objectTypeData := fileProvider.LoadFile(d2common.ObjectType)
|
||||
streamReader := d2common.CreateStreamReader(objectTypeData)
|
||||
count := streamReader.GetInt32()
|
||||
ObjectTypes = make([]ObjectTypeRecord, count)
|
||||
for i := range ObjectTypes {
|
357
d2data/datadict/Objects.go
Normal file
357
d2data/datadict/Objects.go
Normal file
@ -0,0 +1,357 @@
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
// An ObjectRecord represents the settings for one type of object from objects.txt
|
||||
type ObjectRecord struct {
|
||||
Name string
|
||||
Description string
|
||||
Id int
|
||||
Token string // refers to what graphics this object uses
|
||||
|
||||
SpawnMax int // unused?
|
||||
Selectable [8]bool // is this mode selectable
|
||||
TrapProbability int // unused
|
||||
|
||||
SizeX int
|
||||
SizeY int
|
||||
|
||||
NTgtFX int // unknown
|
||||
NTgtFY int // unknown
|
||||
NTgtBX int // unknown
|
||||
NTgtBY int // unknown
|
||||
|
||||
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)
|
||||
CycleAnimation [8]bool // probably whether animation loops
|
||||
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
|
||||
BlockVisibility bool // only works with IsDoor
|
||||
Orientation int // unknown (1=sw, 2=nw, 3=se, 4=ne)
|
||||
Trans int // controls palette mapping
|
||||
|
||||
OrderFlag [8]int // 0 = object, 1 = floor, 2 = wall
|
||||
PreOperate bool // unknown
|
||||
HasAnimationMode [8]bool // 'Mode' in source, true if this mode is used
|
||||
|
||||
XOffset int // in pixels offset
|
||||
YOffset int
|
||||
Draw bool // if false, object isn't drawn (shadow is still drawn and player can still select though)
|
||||
|
||||
LightRed byte // if lightdiameter is set, rgb of the light
|
||||
LightGreen byte
|
||||
LightBlue byte
|
||||
|
||||
SelHD bool // whether these DCC components are selectable
|
||||
SelTR bool
|
||||
SelLG bool
|
||||
SelRA bool
|
||||
SelLA bool
|
||||
SelRH bool
|
||||
SelLH bool
|
||||
SelSH bool
|
||||
SelS [8]bool
|
||||
|
||||
TotalPieces int // selectable DCC components count
|
||||
SubClass int // subclass of object:
|
||||
// 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
|
||||
|
||||
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
|
||||
CollisionSubst bool // unknown, controls some kind of special collision checking?
|
||||
|
||||
Left int // unknown, clickable bounding box?
|
||||
Top int
|
||||
Width int
|
||||
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)
|
||||
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
|
||||
// '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
|
||||
func createObjectRecord(props []string) ObjectRecord {
|
||||
i := -1
|
||||
inc := func() int {
|
||||
i++
|
||||
return i
|
||||
}
|
||||
result := ObjectRecord{
|
||||
Name: props[inc()],
|
||||
Description: props[inc()],
|
||||
Id: dh.StringToInt(props[inc()]),
|
||||
Token: props[inc()],
|
||||
|
||||
SpawnMax: dh.StringToInt(props[inc()]),
|
||||
Selectable: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
TrapProbability: dh.StringToInt(props[inc()]),
|
||||
|
||||
SizeX: dh.StringToInt(props[inc()]),
|
||||
SizeY: dh.StringToInt(props[inc()]),
|
||||
|
||||
NTgtFX: dh.StringToInt(props[inc()]),
|
||||
NTgtFY: dh.StringToInt(props[inc()]),
|
||||
NTgtBX: dh.StringToInt(props[inc()]),
|
||||
NTgtBY: dh.StringToInt(props[inc()]),
|
||||
|
||||
FrameCount: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
FrameDelta: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
CycleAnimation: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
LightDiameter: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
BlocksLight: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
HasCollision: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
IsAttackable: dh.StringToUint8(props[inc()]) == 1,
|
||||
StartFrame: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
|
||||
EnvEffect: dh.StringToUint8(props[inc()]) == 1,
|
||||
IsDoor: dh.StringToUint8(props[inc()]) == 1,
|
||||
BlockVisibility: dh.StringToUint8(props[inc()]) == 1,
|
||||
Orientation: dh.StringToInt(props[inc()]),
|
||||
Trans: dh.StringToInt(props[inc()]),
|
||||
|
||||
OrderFlag: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
PreOperate: dh.StringToUint8(props[inc()]) == 1,
|
||||
HasAnimationMode: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
|
||||
XOffset: dh.StringToInt(props[inc()]),
|
||||
YOffset: dh.StringToInt(props[inc()]),
|
||||
Draw: dh.StringToUint8(props[inc()]) == 1,
|
||||
|
||||
LightRed: dh.StringToUint8(props[inc()]),
|
||||
LightGreen: dh.StringToUint8(props[inc()]),
|
||||
LightBlue: dh.StringToUint8(props[inc()]),
|
||||
|
||||
SelHD: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelTR: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelLG: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelRA: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelLA: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelRH: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelLH: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelSH: dh.StringToUint8(props[inc()]) == 1,
|
||||
SelS: [8]bool{
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
dh.StringToUint8(props[inc()]) == 1,
|
||||
},
|
||||
|
||||
TotalPieces: dh.StringToInt(props[inc()]),
|
||||
SubClass: dh.StringToInt(props[inc()]),
|
||||
|
||||
XSpace: dh.StringToInt(props[inc()]),
|
||||
YSpace: dh.StringToInt(props[inc()]),
|
||||
|
||||
NameOffset: dh.StringToInt(props[inc()]),
|
||||
|
||||
MonsterOk: dh.StringToUint8(props[inc()]) == 1,
|
||||
OperateRange: dh.StringToInt(props[inc()]),
|
||||
ShrineFunction: dh.StringToInt(props[inc()]),
|
||||
Restore: dh.StringToUint8(props[inc()]) == 1,
|
||||
|
||||
Parm: [8]int{
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
dh.StringToInt(props[inc()]),
|
||||
},
|
||||
Act: dh.StringToInt(props[inc()]),
|
||||
Lockable: dh.StringToUint8(props[inc()]) == 1,
|
||||
Gore: dh.StringToUint8(props[inc()]) == 1,
|
||||
Sync: dh.StringToUint8(props[inc()]) == 1,
|
||||
Flicker: dh.StringToUint8(props[inc()]) == 1,
|
||||
Damage: dh.StringToInt(props[inc()]),
|
||||
Beta: dh.StringToUint8(props[inc()]) == 1,
|
||||
Overlay: dh.StringToUint8(props[inc()]) == 1,
|
||||
CollisionSubst: dh.StringToUint8(props[inc()]) == 1,
|
||||
|
||||
Left: dh.StringToInt(props[inc()]),
|
||||
Top: dh.StringToInt(props[inc()]),
|
||||
Width: dh.StringToInt(props[inc()]),
|
||||
Height: dh.StringToInt(props[inc()]),
|
||||
|
||||
OperateFn: dh.StringToInt(props[inc()]),
|
||||
PopulateFn: dh.StringToInt(props[inc()]),
|
||||
InitFn: dh.StringToInt(props[inc()]),
|
||||
ClientFn: dh.StringToInt(props[inc()]),
|
||||
|
||||
RestoreVirgins: dh.StringToUint8(props[inc()]) == 1,
|
||||
BlockMissile: dh.StringToUint8(props[inc()]) == 1,
|
||||
DrawUnder: dh.StringToUint8(props[inc()]) == 1,
|
||||
OpenWarp: dh.StringToUint8(props[inc()]) == 1,
|
||||
|
||||
AutoMap: dh.StringToInt(props[inc()]),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var Objects map[int]*ObjectRecord
|
||||
|
||||
func LoadObjects(fileProvider d2interface.FileProvider) {
|
||||
Objects = make(map[int]*ObjectRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.ObjectDetails)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
props := strings.Split(line, "\t")
|
||||
if props[2] == "" {
|
||||
continue // skip a line that doesn't have an id
|
||||
}
|
||||
rec := createObjectRecord(props)
|
||||
Objects[rec.Id] = &rec
|
||||
}
|
||||
log.Printf("Loaded %d objects", len(Objects))
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
)
|
||||
|
||||
// PaletteRGB represents a color in a palette
|
||||
@ -13,14 +15,14 @@ type PaletteRGB struct {
|
||||
|
||||
// PaletteType represents a palette
|
||||
type PaletteRec struct {
|
||||
Name palettedefs.PaletteType
|
||||
Name d2enum.PaletteType
|
||||
Colors [256]PaletteRGB
|
||||
}
|
||||
|
||||
var Palettes map[palettedefs.PaletteType]PaletteRec
|
||||
var Palettes map[d2enum.PaletteType]PaletteRec
|
||||
|
||||
// CreatePalette creates a palette
|
||||
func CreatePalette(name palettedefs.PaletteType, data []byte) PaletteRec {
|
||||
func CreatePalette(name d2enum.PaletteType, data []byte) PaletteRec {
|
||||
result := PaletteRec{Name: name}
|
||||
|
||||
for i := 0; i <= 255; i++ {
|
||||
@ -33,14 +35,14 @@ func CreatePalette(name palettedefs.PaletteType, data []byte) PaletteRec {
|
||||
return result
|
||||
}
|
||||
|
||||
func LoadPalettes(mpqFiles map[string]string, fileProvider FileProvider) {
|
||||
Palettes = make(map[palettedefs.PaletteType]PaletteRec)
|
||||
func LoadPalettes(mpqFiles map[string]string, fileProvider d2interface.FileProvider) {
|
||||
Palettes = make(map[d2enum.PaletteType]PaletteRec)
|
||||
for _, pal := range []string{
|
||||
"act1", "act2", "act3", "act4", "act5", "endgame", "endgame2", "fechar", "loading",
|
||||
"menu0", "menu1", "menu2", "menu3", "menu4", "sky", "static", "trademark", "units",
|
||||
} {
|
||||
filePath := `data\global\palette\` + pal + `\pal.dat`
|
||||
paletteName := palettedefs.PaletteType(pal)
|
||||
paletteName := d2enum.PaletteType(pal)
|
||||
palette := CreatePalette(paletteName, fileProvider.LoadFile(filePath))
|
||||
Palettes[paletteName] = palette
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
// SoundEntry represents a sound entry
|
||||
@ -46,39 +50,39 @@ func createSoundEntry(soundLine string) SoundEntry {
|
||||
}
|
||||
result := SoundEntry{
|
||||
Handle: props[inc()],
|
||||
Index: StringToInt(props[inc()]),
|
||||
Index: dh.StringToInt(props[inc()]),
|
||||
FileName: props[inc()],
|
||||
Volume: StringToUint8(props[inc()]),
|
||||
GroupSize: StringToUint8(props[inc()]),
|
||||
Loop: StringToUint8(props[inc()]) == 1,
|
||||
FadeIn: StringToUint8(props[inc()]),
|
||||
FadeOut: StringToUint8(props[inc()]),
|
||||
DeferInst: StringToUint8(props[inc()]),
|
||||
StopInst: StringToUint8(props[inc()]),
|
||||
Duration: StringToUint8(props[inc()]),
|
||||
Compound: StringToInt8(props[inc()]),
|
||||
Reverb: StringToUint8(props[inc()]) == 1,
|
||||
Falloff: StringToUint8(props[inc()]),
|
||||
Cache: StringToUint8(props[inc()]),
|
||||
AsyncOnly: StringToUint8(props[inc()]) == 1,
|
||||
Priority: StringToUint8(props[inc()]),
|
||||
Stream: StringToUint8(props[inc()]),
|
||||
Stereo: StringToUint8(props[inc()]),
|
||||
Tracking: StringToUint8(props[inc()]),
|
||||
Solo: StringToUint8(props[inc()]),
|
||||
MusicVol: StringToUint8(props[inc()]),
|
||||
Block1: StringToInt(props[inc()]),
|
||||
Block2: StringToInt(props[inc()]),
|
||||
Block3: StringToInt(props[inc()]),
|
||||
Volume: dh.StringToUint8(props[inc()]),
|
||||
GroupSize: dh.StringToUint8(props[inc()]),
|
||||
Loop: dh.StringToUint8(props[inc()]) == 1,
|
||||
FadeIn: dh.StringToUint8(props[inc()]),
|
||||
FadeOut: dh.StringToUint8(props[inc()]),
|
||||
DeferInst: dh.StringToUint8(props[inc()]),
|
||||
StopInst: dh.StringToUint8(props[inc()]),
|
||||
Duration: dh.StringToUint8(props[inc()]),
|
||||
Compound: dh.StringToInt8(props[inc()]),
|
||||
Reverb: dh.StringToUint8(props[inc()]) == 1,
|
||||
Falloff: dh.StringToUint8(props[inc()]),
|
||||
Cache: dh.StringToUint8(props[inc()]),
|
||||
AsyncOnly: dh.StringToUint8(props[inc()]) == 1,
|
||||
Priority: dh.StringToUint8(props[inc()]),
|
||||
Stream: dh.StringToUint8(props[inc()]),
|
||||
Stereo: dh.StringToUint8(props[inc()]),
|
||||
Tracking: dh.StringToUint8(props[inc()]),
|
||||
Solo: dh.StringToUint8(props[inc()]),
|
||||
MusicVol: dh.StringToUint8(props[inc()]),
|
||||
Block1: dh.StringToInt(props[inc()]),
|
||||
Block2: dh.StringToInt(props[inc()]),
|
||||
Block3: dh.StringToInt(props[inc()]),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var Sounds map[string]SoundEntry
|
||||
|
||||
func LoadSounds(fileProvider FileProvider) {
|
||||
func LoadSounds(fileProvider d2interface.FileProvider) {
|
||||
Sounds = make(map[string]SoundEntry)
|
||||
soundData := strings.Split(string(fileProvider.LoadFile(resourcepaths.SoundSettings)), "\r\n")[1:]
|
||||
soundData := strings.Split(string(fileProvider.LoadFile(d2common.SoundSettings)), "\r\n")[1:]
|
||||
for _, line := range soundData {
|
||||
if len(line) == 0 {
|
||||
continue
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type UniqueItemRecord struct {
|
||||
@ -56,22 +60,22 @@ func createUniqueItemRecord(r []string) UniqueItemRecord {
|
||||
}
|
||||
result := UniqueItemRecord{
|
||||
Name: r[inc()],
|
||||
Version: StringToInt(EmptyToZero(r[inc()])),
|
||||
Enabled: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Version: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
Enabled: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
Ladder: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Rarity: StringToInt(EmptyToZero(r[inc()])),
|
||||
NoLimit: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
Ladder: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
Rarity: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
NoLimit: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
|
||||
Level: StringToInt(EmptyToZero(r[inc()])),
|
||||
RequiredLevel: StringToInt(EmptyToZero(r[inc()])),
|
||||
Level: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
RequiredLevel: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
Code: r[inc()],
|
||||
|
||||
TypeDescription: r[inc()],
|
||||
UberDescription: r[inc()],
|
||||
SingleCopy: StringToInt(EmptyToZero(r[inc()])) == 1,
|
||||
CostMultiplier: StringToInt(EmptyToZero(r[inc()])),
|
||||
CostAdd: StringToInt(EmptyToZero(r[inc()])),
|
||||
SingleCopy: dh.StringToInt(dh.EmptyToZero(r[inc()])) == 1,
|
||||
CostMultiplier: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
CostAdd: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
|
||||
CharacterGfxTransform: r[inc()],
|
||||
InventoryGfxTransform: r[inc()],
|
||||
@ -79,7 +83,7 @@ func createUniqueItemRecord(r []string) UniqueItemRecord {
|
||||
InventoryFile: r[inc()],
|
||||
|
||||
DropSound: r[inc()],
|
||||
DropSfxFrame: StringToInt(EmptyToZero(r[inc()])),
|
||||
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(r[inc()])),
|
||||
UseSound: r[inc()],
|
||||
|
||||
Properties: [12]UniqueItemProperty{
|
||||
@ -106,17 +110,17 @@ func createUniqueItemProperty(r *[]string, inc func() int) UniqueItemProperty {
|
||||
result := UniqueItemProperty{
|
||||
Property: (*r)[inc()],
|
||||
Parameter: (*r)[inc()],
|
||||
Min: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Max: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Min: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
Max: dh.StringToInt(dh.EmptyToZero((*r)[inc()])),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var UniqueItems map[string]*UniqueItemRecord
|
||||
|
||||
func LoadUniqueItems(fileProvider FileProvider) {
|
||||
func LoadUniqueItems(fileProvider d2interface.FileProvider) {
|
||||
UniqueItems = make(map[string]*UniqueItemRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.UniqueItems)), "\r\n")[1:]
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.UniqueItems)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
@ -1,10 +1,14 @@
|
||||
package common
|
||||
package datadict
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
dh "github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
)
|
||||
|
||||
type WeaponRecord struct {
|
||||
@ -134,36 +138,36 @@ func createWeaponRecord(line string) WeaponRecord {
|
||||
Code: r[inc()],
|
||||
AlternateGfx: r[inc()],
|
||||
NameString: r[inc()],
|
||||
Version: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
CompactSave: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Rarity: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Spawnable: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MaxDamage: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
BarbOneOrTwoHanded: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
UsesTwoHands: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Min2HandDamage: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Max2HandDamage: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MinMissileDamage: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MaxMissileDamage: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MissileSpeed: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ExtraRange: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Speed: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
StrengthBonus: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
DexterityBonus: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
RequiredDexterity: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Durability: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
NoDurability: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
RequiredLevel: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Cost: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
GambleCost: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MagicLevel: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
AutoPrefix: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
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()],
|
||||
@ -171,61 +175,61 @@ func createWeaponRecord(line string) WeaponRecord {
|
||||
|
||||
WeaponClass: r[inc()],
|
||||
WeaponClass2Hand: r[inc()],
|
||||
Component: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Component: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
HitClass: r[inc()],
|
||||
InventoryWidth: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
InventoryHeight: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Stackable: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
MinStack: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
MaxStack: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
SpawnStack: StringToInt(EmptyToZero(AsterToEmpty(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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
GemSockets: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
GemApplyType: StringToInt(EmptyToZero(AsterToEmpty(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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Useable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
||||
|
||||
DropSound: r[inc()],
|
||||
DropSfxFrame: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
DropSfxFrame: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
UseSound: r[inc()],
|
||||
|
||||
Unique: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Transparent: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
TransTable: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Quivered: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
LightRadius: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
Belt: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
QuestDifficultyCheck: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Quest: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
QuestDifficultyCheck: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
||||
|
||||
MissileType: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
DurabilityWarning: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
QuantityWarning: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
GemOffset: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
BitField1: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
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: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
InventoryColorTransform: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))),
|
||||
ColorTransform: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
InventoryColorTransform: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))),
|
||||
|
||||
SkipName: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
SkipName: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
||||
NightmareUpgrade: r[inc()],
|
||||
HellUpgrade: r[inc()],
|
||||
|
||||
Nameable: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
PermStoreItem: StringToInt(EmptyToZero(AsterToEmpty(r[inc()]))) == 1,
|
||||
Nameable: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
||||
PermStoreItem: dh.StringToInt(dh.EmptyToZero(dh.AsterToEmpty(r[inc()]))) == 1,
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -258,11 +262,11 @@ func CreateItemVendorParams(r *[]string, inc func() int, vs []string) map[string
|
||||
|
||||
for _, name := range vs {
|
||||
wvp := ItemVendorParams{
|
||||
Min: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
Max: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
MagicMin: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
MagicMax: StringToInt(EmptyToZero((*r)[inc()])),
|
||||
MagicLevel: StringToUint8(EmptyToZero((*r)[inc()])),
|
||||
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
|
||||
}
|
||||
@ -271,9 +275,9 @@ func CreateItemVendorParams(r *[]string, inc func() int, vs []string) map[string
|
||||
|
||||
var Weapons map[string]*WeaponRecord
|
||||
|
||||
func LoadWeapons(fileProvider FileProvider) {
|
||||
func LoadWeapons(fileProvider d2interface.FileProvider) {
|
||||
Weapons = make(map[string]*WeaponRecord)
|
||||
data := strings.Split(string(fileProvider.LoadFile(resourcepaths.Weapons)), "\r\n")[1:]
|
||||
data := strings.Split(string(fileProvider.LoadFile(d2common.Weapons)), "\r\n")[1:]
|
||||
for _, line := range data {
|
||||
if len(line) == 0 {
|
||||
continue
|
@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
// MPQ represents an MPQ archive
|
||||
@ -260,7 +260,7 @@ func (v MPQ) FileExists(fileName string) bool {
|
||||
|
||||
// ReadFile reads a file from the MPQ and returns a memory stream
|
||||
func (v MPQ) ReadFile(fileName string) ([]byte, error) {
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", resourcepaths.LanguageCode)
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", d2common.LanguageCode)
|
||||
fileName = strings.ToLower(fileName)
|
||||
fileName = strings.ReplaceAll(fileName, `/`, "\\")
|
||||
cached := v.fileCache[fileName]
|
@ -9,9 +9,10 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/JoshVarga/blast"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/compression"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/compression"
|
||||
)
|
||||
|
||||
// Stream represents a stream of data in an MPQ archive
|
||||
@ -98,7 +99,7 @@ func (v *Stream) readInternalSingleUnit(buffer []byte, offset, count uint32) uin
|
||||
v.loadSingleUnit()
|
||||
}
|
||||
|
||||
bytesToCopy := common.Min(uint32(len(v.CurrentData))-v.CurrentPosition, count)
|
||||
bytesToCopy := d2helper.Min(uint32(len(v.CurrentData))-v.CurrentPosition, count)
|
||||
copy(buffer[offset:offset+bytesToCopy], v.CurrentData[v.CurrentPosition:v.CurrentPosition+bytesToCopy])
|
||||
v.CurrentPosition += bytesToCopy
|
||||
return bytesToCopy
|
||||
@ -107,7 +108,7 @@ func (v *Stream) readInternalSingleUnit(buffer []byte, offset, count uint32) uin
|
||||
func (v *Stream) readInternal(buffer []byte, offset, count uint32) uint32 {
|
||||
v.bufferData()
|
||||
localPosition := v.CurrentPosition % v.BlockSize
|
||||
bytesToCopy := common.MinInt32(int32(len(v.CurrentData))-int32(localPosition), int32(count))
|
||||
bytesToCopy := d2helper.MinInt32(int32(len(v.CurrentData))-int32(localPosition), int32(count))
|
||||
if bytesToCopy <= 0 {
|
||||
return 0
|
||||
}
|
||||
@ -121,7 +122,7 @@ func (v *Stream) bufferData() {
|
||||
if requiredBlock == v.CurrentBlockIndex {
|
||||
return
|
||||
}
|
||||
expectedLength := common.Min(v.BlockTableEntry.UncompressedFileSize-(requiredBlock*v.BlockSize), v.BlockSize)
|
||||
expectedLength := d2helper.Min(v.BlockTableEntry.UncompressedFileSize-(requiredBlock*v.BlockSize), v.BlockSize)
|
||||
v.CurrentData = v.loadBlock(requiredBlock, expectedLength)
|
||||
v.CurrentBlockIndex = requiredBlock
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package mpq
|
||||
|
||||
type MpqFileRecord struct {
|
||||
MpqFile string
|
@ -3,7 +3,7 @@ package video
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
type BinkVideoMode uint32
|
||||
@ -41,7 +41,7 @@ type BinkDecoder struct {
|
||||
VideoHeight uint32
|
||||
FPS uint32
|
||||
FrameTimeMS uint32
|
||||
streamReader *common.StreamReader
|
||||
streamReader *d2common.StreamReader
|
||||
VideoMode BinkVideoMode
|
||||
HasAlphaPlane bool
|
||||
Grayscale bool
|
||||
@ -52,7 +52,7 @@ type BinkDecoder struct {
|
||||
|
||||
func CreateBinkDecoder(source []byte) *BinkDecoder {
|
||||
result := &BinkDecoder{
|
||||
streamReader: common.CreateStreamReader(source),
|
||||
streamReader: d2common.CreateStreamReader(source),
|
||||
}
|
||||
result.loadHeaderInformation()
|
||||
return result
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2helper
|
||||
|
||||
import (
|
||||
"image/color"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2helper
|
||||
|
||||
// Min returns the lower of two values
|
||||
func Min(a, b uint32) uint32 {
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2helper
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2render
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,7 +6,17 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
@ -19,9 +29,9 @@ type AnimatedEntity struct {
|
||||
LocationX float64
|
||||
// LocationY represents the tile Y position of the entity
|
||||
LocationY float64
|
||||
dccLayers map[string]*DCC
|
||||
Cof *Cof
|
||||
palette palettedefs.PaletteType
|
||||
dccLayers map[string]*d2data.DCC
|
||||
Cof *d2data.Cof
|
||||
palette d2enum.PaletteType
|
||||
base string
|
||||
token string
|
||||
animationMode string
|
||||
@ -32,19 +42,19 @@ type AnimatedEntity struct {
|
||||
direction int
|
||||
currentFrame int
|
||||
frames map[string][]*ebiten.Image
|
||||
frameLocations map[string][]Rectangle
|
||||
object Object
|
||||
frameLocations map[string][]d2common.Rectangle
|
||||
object d2data.Object
|
||||
}
|
||||
|
||||
// CreateAnimatedEntity creates an instance of AnimatedEntity
|
||||
func CreateAnimatedEntity(object Object, fileProvider FileProvider, palette palettedefs.PaletteType) *AnimatedEntity {
|
||||
func CreateAnimatedEntity(object d2data.Object, fileProvider d2interface.FileProvider, palette d2enum.PaletteType) *AnimatedEntity {
|
||||
result := &AnimatedEntity{
|
||||
base: object.Lookup.Base,
|
||||
token: object.Lookup.Token,
|
||||
object: object,
|
||||
palette: palette,
|
||||
}
|
||||
result.dccLayers = make(map[string]*DCC)
|
||||
result.dccLayers = make(map[string]*d2data.DCC)
|
||||
result.LocationX = float64(object.X) / 5
|
||||
result.LocationY = float64(object.Y) / 5
|
||||
return result
|
||||
@ -54,9 +64,9 @@ func CreateAnimatedEntity(object Object, fileProvider FileProvider, palette pale
|
||||
var DirectionLookup = []int{3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14}
|
||||
|
||||
// SetMode changes the graphical mode of this animated entity
|
||||
func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction int, provider FileProvider) {
|
||||
func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction int, provider d2interface.FileProvider) {
|
||||
cofPath := fmt.Sprintf("%s/%s/Cof/%s%s%s.Cof", v.base, v.token, v.token, animationMode, weaponClass)
|
||||
v.Cof = LoadCof(cofPath, provider)
|
||||
v.Cof = d2data.LoadCof(cofPath, provider)
|
||||
v.animationMode = animationMode
|
||||
v.weaponClass = weaponClass
|
||||
v.direction = direction
|
||||
@ -64,8 +74,8 @@ func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction in
|
||||
v.direction = v.Cof.NumberOfDirections - 1
|
||||
}
|
||||
v.frames = make(map[string][]*ebiten.Image)
|
||||
v.frameLocations = make(map[string][]Rectangle)
|
||||
v.dccLayers = make(map[string]*DCC)
|
||||
v.frameLocations = make(map[string][]d2common.Rectangle)
|
||||
v.dccLayers = make(map[string]*d2data.DCC)
|
||||
for _, cofLayer := range v.Cof.CofLayers {
|
||||
layerName := DccLayerNames[cofLayer.Type]
|
||||
v.dccLayers[layerName] = v.LoadLayer(layerName, provider)
|
||||
@ -77,7 +87,7 @@ func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction in
|
||||
|
||||
}
|
||||
|
||||
func (v *AnimatedEntity) LoadLayer(layer string, fileProvider FileProvider) *DCC {
|
||||
func (v *AnimatedEntity) LoadLayer(layer string, fileProvider d2interface.FileProvider) *d2data.DCC {
|
||||
layerName := "tr"
|
||||
switch strings.ToUpper(layer) {
|
||||
case "HD": // Head
|
||||
@ -117,7 +127,7 @@ func (v *AnimatedEntity) LoadLayer(layer string, fileProvider FileProvider) *DCC
|
||||
return nil
|
||||
}
|
||||
dccPath := fmt.Sprintf("%s/%s/%s/%s%s%s%s%s.dcc", v.base, v.token, layer, v.token, layer, layerName, v.animationMode, v.weaponClass)
|
||||
return LoadDCC(dccPath, fileProvider)
|
||||
return d2data.LoadDCC(dccPath, fileProvider)
|
||||
}
|
||||
|
||||
// Render draws this animated entity onto the target
|
||||
@ -149,7 +159,7 @@ func (v *AnimatedEntity) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||
dcc := v.dccLayers[layerName]
|
||||
v.currentFrame = 0
|
||||
animationData := AnimationData[strings.ToLower(v.token+v.animationMode+v.weaponClass)][0]
|
||||
animationData := d2data.AnimationData[strings.ToLower(v.token+v.animationMode+v.weaponClass)][0]
|
||||
v.animationSpeed = int(1000.0 / ((float64(animationData.AnimationSpeed) * 25.0) / 256.0))
|
||||
v.framesToAnimate = animationData.FramesPerDirection
|
||||
v.lastFrameTime = time.Now()
|
||||
@ -158,15 +168,15 @@ func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||
maxX := int32(-10000)
|
||||
maxY := int32(-10000)
|
||||
for _, layer := range dcc.Directions {
|
||||
minX = MinInt32(minX, int32(layer.Box.Left))
|
||||
minY = MinInt32(minY, int32(layer.Box.Top))
|
||||
maxX = MaxInt32(maxX, int32(layer.Box.Right()))
|
||||
maxY = MaxInt32(maxY, int32(layer.Box.Bottom()))
|
||||
minX = d2helper.MinInt32(minX, int32(layer.Box.Left))
|
||||
minY = d2helper.MinInt32(minY, int32(layer.Box.Top))
|
||||
maxX = d2helper.MaxInt32(maxX, int32(layer.Box.Right()))
|
||||
maxY = d2helper.MaxInt32(maxY, int32(layer.Box.Bottom()))
|
||||
}
|
||||
frameW := maxX - minX
|
||||
frameH := maxY - minY
|
||||
v.frames[layerName] = make([]*ebiten.Image, v.framesToAnimate)
|
||||
v.frameLocations[layerName] = make([]Rectangle, v.framesToAnimate)
|
||||
v.frameLocations[layerName] = make([]d2common.Rectangle, v.framesToAnimate)
|
||||
for frameIndex := range v.frames[layerName] {
|
||||
v.frames[layerName][frameIndex], _ = ebiten.NewImage(int(frameW), int(frameH), ebiten.FilterNearest)
|
||||
for layerIdx := 0; layerIdx < v.Cof.NumberOfLayers; layerIdx++ {
|
||||
@ -185,7 +195,7 @@ func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||
if paletteIndex == 0 {
|
||||
continue
|
||||
}
|
||||
color := Palettes[v.palette].Colors[paletteIndex]
|
||||
color := datadict.Palettes[v.palette].Colors[paletteIndex]
|
||||
actualX := x + direction.Box.Left - int(minX)
|
||||
actualY := y + direction.Box.Top - int(minY)
|
||||
img.Pix[(actualX*4)+(actualY*int(frameW)*4)] = color.R
|
||||
@ -197,7 +207,7 @@ func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||
newImage, _ := ebiten.NewImageFromImage(img, ebiten.FilterNearest)
|
||||
img = nil
|
||||
v.frames[layerName][frameIndex] = newImage
|
||||
v.frameLocations[layerName][frameIndex] = Rectangle{
|
||||
v.frameLocations[layerName][frameIndex] = d2common.Rectangle{
|
||||
Left: int(minX),
|
||||
Top: int(minY),
|
||||
Width: int(frameW),
|
27
d2render/NPC.go
Normal file
27
d2render/NPC.go
Normal file
@ -0,0 +1,27 @@
|
||||
package d2render
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type NPC struct {
|
||||
AnimatedEntity *AnimatedEntity
|
||||
Paths []d2common.Path
|
||||
}
|
||||
|
||||
func CreateNPC(object d2data.Object, fileProvider d2interface.FileProvider) *NPC {
|
||||
result := &NPC{
|
||||
AnimatedEntity: CreateAnimatedEntity(object, fileProvider, d2enum.Units),
|
||||
Paths: object.Paths,
|
||||
}
|
||||
result.AnimatedEntity.SetMode(object.Lookup.Mode, object.Lookup.Class, 1, fileProvider)
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *NPC) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
v.AnimatedEntity.Render(target, offsetX, offsetY)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package d2render
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@ -7,6 +7,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -45,7 +49,7 @@ type SpriteFrame struct {
|
||||
}
|
||||
|
||||
// CreateSprite creates an instance of a sprite
|
||||
func CreateSprite(data []byte, palette PaletteRec) *Sprite {
|
||||
func CreateSprite(data []byte, palette datadict.PaletteRec) *Sprite {
|
||||
result := &Sprite{
|
||||
X: 50,
|
||||
Y: 50,
|
||||
@ -81,9 +85,9 @@ func CreateSprite(data []byte, palette PaletteRec) *Sprite {
|
||||
dataPointer += 4
|
||||
result.Frames[i].Height = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
||||
dataPointer += 4
|
||||
result.Frames[i].OffsetX = BytesToInt32(data[dataPointer : dataPointer+4])
|
||||
result.Frames[i].OffsetX = d2helper.BytesToInt32(data[dataPointer : dataPointer+4])
|
||||
dataPointer += 4
|
||||
result.Frames[i].OffsetY = BytesToInt32(data[dataPointer : dataPointer+4])
|
||||
result.Frames[i].OffsetY = d2helper.BytesToInt32(data[dataPointer : dataPointer+4])
|
||||
dataPointer += 4
|
||||
result.Frames[i].Unknown = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
||||
dataPointer += 4
|
||||
@ -143,7 +147,7 @@ func CreateSprite(data []byte, palette PaletteRec) *Sprite {
|
||||
for d := 0; d < int(result.Directions); d++ {
|
||||
curMaxWidth := 0
|
||||
for f := 0; f < int(result.FramesPerDirection); f++ {
|
||||
curMaxWidth = int(Max(uint32(curMaxWidth), result.Frames[frame].Width))
|
||||
curMaxWidth = int(d2helper.Max(uint32(curMaxWidth), result.Frames[frame].Width))
|
||||
totalHeight += int(result.Frames[frame].Height)
|
||||
frame++
|
||||
}
|
||||
@ -157,7 +161,7 @@ func CreateSprite(data []byte, palette PaletteRec) *Sprite {
|
||||
for d := 0; d < int(result.Directions); d++ {
|
||||
curMaxWidth := 0
|
||||
for f := 0; f < int(result.FramesPerDirection); f++ {
|
||||
curMaxWidth = int(Max(uint32(curMaxWidth), result.Frames[frame].Width))
|
||||
curMaxWidth = int(d2helper.Max(uint32(curMaxWidth), result.Frames[frame].Width))
|
||||
result.Frames[frame].Image = result.atlas.SubImage(image.Rect(curX, curY, curX+int(result.Frames[frame].Width), curY+int(result.Frames[frame].Height))).(*ebiten.Image)
|
||||
curY += int(result.Frames[frame].Height)
|
||||
frame++
|
||||
@ -260,7 +264,7 @@ func (v *Sprite) Draw(target *ebiten.Image) {
|
||||
opts.CompositeMode = ebiten.CompositeModeSourceOver
|
||||
}
|
||||
if v.ColorMod != nil {
|
||||
opts.ColorM = ColorToColorM(v.ColorMod)
|
||||
opts.ColorM = d2helper.ColorToColorM(v.ColorMod)
|
||||
}
|
||||
target.DrawImage(frame.Image, opts)
|
||||
}
|
||||
@ -288,11 +292,11 @@ func (v *Sprite) DrawSegments(target *ebiten.Image, xSegments, ySegments, offset
|
||||
opts.CompositeMode = ebiten.CompositeModeSourceOver
|
||||
}
|
||||
if v.ColorMod != nil {
|
||||
opts.ColorM = ColorToColorM(v.ColorMod)
|
||||
opts.ColorM = d2helper.ColorToColorM(v.ColorMod)
|
||||
}
|
||||
target.DrawImage(frame.Image, opts)
|
||||
xOffset += int32(frame.Width)
|
||||
biggestYOffset = MaxInt32(biggestYOffset, int32(frame.Height))
|
||||
biggestYOffset = d2helper.MaxInt32(biggestYOffset, int32(frame.Height))
|
||||
}
|
||||
yOffset += biggestYOffset
|
||||
}
|
@ -1,30 +1,36 @@
|
||||
package _map
|
||||
package mapengine
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type EngineRegion struct {
|
||||
Rect common.Rectangle
|
||||
Rect d2common.Rectangle
|
||||
Region *Region
|
||||
}
|
||||
|
||||
type Engine struct {
|
||||
soundManager *sound.Manager
|
||||
gameState *common.GameState
|
||||
fileProvider common.FileProvider
|
||||
soundManager *d2audio.Manager
|
||||
gameState *d2core.GameState
|
||||
fileProvider d2interface.FileProvider
|
||||
regions []EngineRegion
|
||||
OffsetX float64
|
||||
OffsetY float64
|
||||
}
|
||||
|
||||
func CreateMapEngine(gameState *common.GameState, soundManager *sound.Manager, fileProvider common.FileProvider) *Engine {
|
||||
func CreateMapEngine(gameState *d2core.GameState, soundManager *d2audio.Manager, fileProvider d2interface.FileProvider) *Engine {
|
||||
result := &Engine{
|
||||
gameState: gameState,
|
||||
soundManager: soundManager,
|
||||
@ -38,7 +44,7 @@ func (v *Engine) GenerateMap(regionType RegionIdType, levelPreset int) {
|
||||
randomSource := rand.NewSource(v.gameState.Seed)
|
||||
region := LoadRegion(randomSource, regionType, levelPreset, v.fileProvider)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Rect: d2common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Region: region,
|
||||
})
|
||||
}
|
||||
@ -48,24 +54,24 @@ func (v *Engine) GenerateAct1Overworld() {
|
||||
randomSource := rand.NewSource(v.gameState.Seed)
|
||||
region := LoadRegion(randomSource, RegionAct1Town, 1, v.fileProvider)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Rect: d2common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Region: region,
|
||||
})
|
||||
if strings.Contains(region.RegionPath, "E1") {
|
||||
region2 := LoadRegion(randomSource, RegionAct1Town, 2, v.fileProvider)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: common.Rectangle{int(region.TileWidth - 1), 0, int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Rect: d2common.Rectangle{int(region.TileWidth - 1), 0, int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Region: region2,
|
||||
})
|
||||
} else if strings.Contains(region.RegionPath, "S1") {
|
||||
region2 := LoadRegion(randomSource, RegionAct1Town, 3, v.fileProvider)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: common.Rectangle{0, int(region.TileHeight - 1), int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Rect: d2common.Rectangle{0, int(region.TileHeight - 1), int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Region: region2,
|
||||
})
|
||||
}
|
||||
|
||||
sx, sy := common.IsoToScreen(int(region.StartX), int(region.StartY), 0, 0)
|
||||
sx, sy := d2helper.IsoToScreen(int(region.StartX), int(region.StartY), 0, 0)
|
||||
v.OffsetX = float64(sx) - 400
|
||||
v.OffsetY = float64(sy) - 300
|
||||
}
|
||||
@ -94,7 +100,7 @@ func (v *Engine) RenderRegion(region EngineRegion, target *ebiten.Image) {
|
||||
offX := -((y + region.Rect.Top) * 80) + (region.Rect.Left * 80)
|
||||
offY := ((y + region.Rect.Top) * 40) + (region.Rect.Left * 40)
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
sx, sy := common.IsoToScreen(x+region.Rect.Left, y+region.Rect.Top, int(v.OffsetX), int(v.OffsetY))
|
||||
sx, sy := d2helper.IsoToScreen(x+region.Rect.Left, y+region.Rect.Top, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 880 && sy <= 1000 {
|
||||
v.RenderTile(region.Region, offX, offY, x, y, target)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package _map
|
||||
package mapengine
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
@ -8,11 +8,19 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
)
|
||||
|
||||
type TileCacheRecord struct {
|
||||
@ -23,18 +31,18 @@ type TileCacheRecord struct {
|
||||
|
||||
type Region struct {
|
||||
RegionPath string
|
||||
LevelType common.LevelTypeRecord
|
||||
levelPreset *common.LevelPresetRecord
|
||||
LevelType datadict.LevelTypeRecord
|
||||
levelPreset *datadict.LevelPresetRecord
|
||||
TileWidth int32
|
||||
TileHeight int32
|
||||
Tiles []Tile
|
||||
DS1 *DS1
|
||||
Palette common.PaletteRec
|
||||
Tiles []d2data.Tile
|
||||
DS1 *d2data.DS1
|
||||
Palette datadict.PaletteRec
|
||||
FloorCache map[uint32]*TileCacheRecord
|
||||
ShadowCache map[uint32]*TileCacheRecord
|
||||
WallCache map[uint32]*TileCacheRecord
|
||||
AnimationEntities []*common.AnimatedEntity
|
||||
NPCs []*common.NPC
|
||||
AnimationEntities []*d2render.AnimatedEntity
|
||||
NPCs []*d2render.NPC
|
||||
StartX float64
|
||||
StartY float64
|
||||
}
|
||||
@ -87,16 +95,16 @@ const (
|
||||
RegionAct5Lava RegionIdType = 35
|
||||
)
|
||||
|
||||
func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileProvider common.FileProvider) *Region {
|
||||
func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileProvider d2interface.FileProvider) *Region {
|
||||
result := &Region{
|
||||
LevelType: common.LevelTypes[levelType],
|
||||
levelPreset: common.LevelPresets[levelPreset],
|
||||
Tiles: make([]Tile, 0),
|
||||
LevelType: datadict.LevelTypes[levelType],
|
||||
levelPreset: datadict.LevelPresets[levelPreset],
|
||||
Tiles: make([]d2data.Tile, 0),
|
||||
FloorCache: make(map[uint32]*TileCacheRecord),
|
||||
ShadowCache: make(map[uint32]*TileCacheRecord),
|
||||
WallCache: make(map[uint32]*TileCacheRecord),
|
||||
}
|
||||
result.Palette = common.Palettes[palettedefs.PaletteType("act"+strconv.Itoa(int(result.LevelType.Act)))]
|
||||
result.Palette = datadict.Palettes[d2enum.PaletteType("act"+strconv.Itoa(int(result.LevelType.Act)))]
|
||||
//\bm := result.levelPreset.Dt1Mask
|
||||
for _, levelTypeDt1 := range result.LevelType.Files {
|
||||
/*
|
||||
@ -109,7 +117,7 @@ func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileP
|
||||
if len(levelTypeDt1) == 0 || levelTypeDt1 == "" || levelTypeDt1 == "0" {
|
||||
continue
|
||||
}
|
||||
dt1 := LoadDT1("/data/global/tiles/"+levelTypeDt1, fileProvider)
|
||||
dt1 := d2data.LoadDT1("/data/global/tiles/"+levelTypeDt1, fileProvider)
|
||||
result.Tiles = append(result.Tiles, dt1.Tiles...)
|
||||
}
|
||||
levelFilesToPick := make([]string, 0)
|
||||
@ -123,34 +131,34 @@ func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileP
|
||||
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * random.Float64()))
|
||||
levelFile := levelFilesToPick[levelIndex]
|
||||
result.RegionPath = levelFile
|
||||
result.DS1 = LoadDS1("/data/global/tiles/"+levelFile, fileProvider)
|
||||
result.DS1 = d2data.LoadDS1("/data/global/tiles/"+levelFile, fileProvider)
|
||||
result.TileWidth = result.DS1.Width
|
||||
result.TileHeight = result.DS1.Height
|
||||
result.loadObjects(fileProvider)
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *Region) loadObjects(fileProvider common.FileProvider) {
|
||||
func (v *Region) loadObjects(fileProvider d2interface.FileProvider) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(v.DS1.Objects))
|
||||
v.AnimationEntities = make([]*common.AnimatedEntity, 0)
|
||||
v.NPCs = make([]*common.NPC, 0)
|
||||
v.AnimationEntities = make([]*d2render.AnimatedEntity, 0)
|
||||
v.NPCs = make([]*d2render.NPC, 0)
|
||||
for _, object := range v.DS1.Objects {
|
||||
go func(object common.Object) {
|
||||
go func(object d2data.Object) {
|
||||
defer wg.Done()
|
||||
switch object.Lookup.Type {
|
||||
case common.ObjectTypeCharacter:
|
||||
case datadict.ObjectTypeCharacter:
|
||||
// Temp code, maybe..
|
||||
if object.Lookup.Base == "" || object.Lookup.Token == "" || object.Lookup.TR == "" {
|
||||
return
|
||||
}
|
||||
npc := common.CreateNPC(object, fileProvider)
|
||||
npc := d2render.CreateNPC(object, fileProvider)
|
||||
v.NPCs = append(v.NPCs, npc)
|
||||
case common.ObjectTypeItem:
|
||||
case datadict.ObjectTypeItem:
|
||||
if object.ObjectInfo == nil || !object.ObjectInfo.Draw || object.Lookup.Base == "" || object.Lookup.Token == "" {
|
||||
return
|
||||
}
|
||||
entity := common.CreateAnimatedEntity(object, fileProvider, palettedefs.Units)
|
||||
entity := d2render.CreateAnimatedEntity(object, fileProvider, d2enum.Units)
|
||||
entity.SetMode(object.Lookup.Mode, object.Lookup.Class, 0, fileProvider)
|
||||
v.AnimationEntities = append(v.AnimationEntities, entity)
|
||||
}
|
||||
@ -171,7 +179,7 @@ func (v *Region) RenderTile(offsetX, offsetY, tileX, tileY int, layerType Region
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Region) getTile(mainIndex, subIndex, orientation int32) *Tile {
|
||||
func (v *Region) getTile(mainIndex, subIndex, orientation int32) *d2data.Tile {
|
||||
// TODO: Need to support randomly grabbing tile based on x/y as there can be multiple matches for same main/sub index
|
||||
for _, tile := range v.Tiles {
|
||||
if tile.MainIndex != mainIndex || tile.SubIndex != subIndex || tile.Orientation != orientation {
|
||||
@ -183,7 +191,7 @@ func (v *Region) getTile(mainIndex, subIndex, orientation int32) *Tile {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Region) renderFloor(tile FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
func (v *Region) renderFloor(tile d2data.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8)
|
||||
tileCache, exists := v.FloorCache[tileCacheIndex]
|
||||
if !exists {
|
||||
@ -198,7 +206,7 @@ func (v *Region) renderFloor(tile FloorShadowRecord, offsetX, offsetY int, targe
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) renderWall(tile WallRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
func (v *Region) renderWall(tile d2data.WallRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8) | (uint32(tile.Orientation))
|
||||
tileCache, exists := v.WallCache[tileCacheIndex]
|
||||
if !exists {
|
||||
@ -213,7 +221,7 @@ func (v *Region) renderWall(tile WallRecord, offsetX, offsetY int, target *ebite
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) renderShadow(tile FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
func (v *Region) renderShadow(tile d2data.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) + (uint32(tile.SubIndex) << 8) + 0
|
||||
tileCache, exists := v.ShadowCache[tileCacheIndex]
|
||||
if !exists {
|
||||
@ -225,13 +233,13 @@ func (v *Region) renderShadow(tile FloorShadowRecord, offsetX, offsetY int, targ
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
|
||||
opts.ColorM = common.ColorToColorM(color.RGBA{255, 255, 255, 160})
|
||||
opts.ColorM = d2helper.ColorToColorM(color.RGBA{255, 255, 255, 160})
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) decodeTileGfxData(blocks []Block, pixels []byte, tileYOffset int32, tileWidth int32) {
|
||||
func (v *Region) decodeTileGfxData(blocks []d2data.Block, pixels []byte, tileYOffset int32, tileWidth int32) {
|
||||
for _, block := range blocks {
|
||||
if block.Format == BlockFormatIsometric {
|
||||
if block.Format == d2data.BlockFormatIsometric {
|
||||
// 3D isometric decoding
|
||||
xjump := []int32{14, 12, 10, 8, 6, 4, 2, 0, 2, 4, 6, 8, 10, 12, 14}
|
||||
nbpix := []int32{4, 8, 12, 16, 20, 24, 28, 32, 28, 24, 20, 16, 12, 8, 4}
|
||||
@ -301,17 +309,17 @@ func (v *Region) decodeTileGfxData(blocks []Block, pixels []byte, tileYOffset in
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
func (v *Region) generateFloorCache(tile d2data.FloorShadowRecord) *TileCacheRecord {
|
||||
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 0)
|
||||
if tileData == nil {
|
||||
log.Fatalf("Could not locate tile Idx:%d, Sub: %d, Ori: %d", tile.MainIndex, tile.SubIndex, 0)
|
||||
}
|
||||
tileYMinimum := int32(0)
|
||||
for _, block := range tileData.Blocks {
|
||||
tileYMinimum = common.MinInt32(tileYMinimum, int32(block.Y))
|
||||
tileYMinimum = d2helper.MinInt32(tileYMinimum, int32(block.Y))
|
||||
}
|
||||
tileYOffset := common.AbsInt32(tileYMinimum)
|
||||
tileHeight := common.AbsInt32(tileData.Height)
|
||||
tileYOffset := d2helper.AbsInt32(tileYMinimum)
|
||||
tileHeight := d2helper.AbsInt32(tileData.Height)
|
||||
image, _ := ebiten.NewImage(int(tileData.Width), int(tileHeight), ebiten.FilterNearest)
|
||||
pixels := make([]byte, 4*tileData.Width*tileHeight)
|
||||
v.decodeTileGfxData(tileData.Blocks, pixels, tileYOffset, tileData.Width)
|
||||
@ -319,7 +327,7 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
return &TileCacheRecord{image, 0, 0}
|
||||
}
|
||||
|
||||
func (v *Region) generateShadowCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
func (v *Region) generateShadowCache(tile d2data.FloorShadowRecord) *TileCacheRecord {
|
||||
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 13)
|
||||
if tileData == nil {
|
||||
return nil
|
||||
@ -327,8 +335,8 @@ func (v *Region) generateShadowCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
tileMinY := int32(0)
|
||||
tileMaxY := int32(0)
|
||||
for _, block := range tileData.Blocks {
|
||||
tileMinY = common.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = common.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
tileMinY = d2helper.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = d2helper.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
}
|
||||
tileYOffset := -tileMinY
|
||||
tileHeight := int(tileMaxY - tileMinY)
|
||||
@ -339,12 +347,12 @@ func (v *Region) generateShadowCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
return &TileCacheRecord{image, 0, int(tileMinY) + 80}
|
||||
}
|
||||
|
||||
func (v *Region) generateWallCache(tile WallRecord) *TileCacheRecord {
|
||||
func (v *Region) generateWallCache(tile d2data.WallRecord) *TileCacheRecord {
|
||||
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), int32(tile.Orientation))
|
||||
if tileData == nil {
|
||||
return nil
|
||||
}
|
||||
var newTileData *Tile = nil
|
||||
var newTileData *d2data.Tile = nil
|
||||
if tile.Orientation == 3 {
|
||||
newTileData = v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), int32(4))
|
||||
}
|
||||
@ -356,10 +364,10 @@ func (v *Region) generateWallCache(tile WallRecord) *TileCacheRecord {
|
||||
target = newTileData
|
||||
}
|
||||
for _, block := range target.Blocks {
|
||||
tileMinY = common.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = common.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
tileMinY = d2helper.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = d2helper.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
}
|
||||
realHeight := common.MaxInt32(common.AbsInt32(tileData.Height), tileMaxY-tileMinY)
|
||||
realHeight := d2helper.MaxInt32(d2helper.AbsInt32(tileData.Height), tileMaxY-tileMinY)
|
||||
tileYOffset := -tileMinY
|
||||
//tileHeight := int(tileMaxY - tileMinY)
|
||||
image, _ := ebiten.NewImage(160, int(realHeight), ebiten.FilterNearest)
|
@ -4,9 +4,16 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -40,25 +47,25 @@ const (
|
||||
|
||||
// ButtonLayout defines the type of buttons
|
||||
type ButtonLayout struct {
|
||||
XSegments int //1
|
||||
YSegments int // 1
|
||||
ResourceName string // Font Name
|
||||
PaletteName palettedefs.PaletteType // PaletteType
|
||||
Toggleable bool // false
|
||||
BaseFrame int // 0
|
||||
DisabledFrame int // -1
|
||||
FontPath string // ResourcePaths.FontExocet10
|
||||
ClickableRect *image.Rectangle // nil
|
||||
AllowFrameChange bool // true
|
||||
TextOffset int // 0
|
||||
XSegments int //1
|
||||
YSegments int // 1
|
||||
ResourceName string // Font Name
|
||||
PaletteName d2enum.PaletteType // PaletteType
|
||||
Toggleable bool // false
|
||||
BaseFrame int // 0
|
||||
DisabledFrame int // -1
|
||||
FontPath string // ResourcePaths.FontExocet10
|
||||
ClickableRect *image.Rectangle // nil
|
||||
AllowFrameChange bool // true
|
||||
TextOffset int // 0
|
||||
}
|
||||
|
||||
// ButtonLayouts define the type of buttons you can have
|
||||
var ButtonLayouts = map[ButtonType]ButtonLayout{
|
||||
ButtonTypeWide: {2, 1, resourcepaths.WideButtonBlank, palettedefs.Units, false, 0, -1, resourcepaths.FontExocet10, nil, true, 1},
|
||||
ButtonTypeShort: {1, 1, resourcepaths.ShortButtonBlank, palettedefs.Units, false, 0, -1, resourcepaths.FontRediculous, nil, true, -1},
|
||||
ButtonTypeMedium: {1, 1, resourcepaths.MediumButtonBlank, palettedefs.Units, false, 0, 0, resourcepaths.FontExocet10, nil, true, 0},
|
||||
ButtonTypeTall: {1, 1, resourcepaths.TallButtonBlank, palettedefs.Units, false, 0, 0, resourcepaths.FontExocet10, nil, true, 5},
|
||||
ButtonTypeWide: {2, 1, d2common.WideButtonBlank, d2enum.Units, false, 0, -1, d2common.FontExocet10, nil, true, 1},
|
||||
ButtonTypeShort: {1, 1, d2common.ShortButtonBlank, d2enum.Units, false, 0, -1, d2common.FontRediculous, nil, true, -1},
|
||||
ButtonTypeMedium: {1, 1, d2common.MediumButtonBlank, d2enum.Units, false, 0, 0, d2common.FontExocet10, nil, true, 0},
|
||||
ButtonTypeTall: {1, 1, d2common.TallButtonBlank, d2enum.Units, false, 0, 0, d2common.FontExocet10, nil, true, 5},
|
||||
/*
|
||||
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = PaletteDefs.Units } },
|
||||
{eButtonType.Narrow, new ButtonLayout { ResourceName = ResourcePaths.NarrowButtonBlank, PaletteName = PaletteDefs.Units } },
|
||||
@ -89,7 +96,7 @@ type Button struct {
|
||||
visible bool
|
||||
pressed bool
|
||||
toggled bool
|
||||
fileProvider common.FileProvider
|
||||
fileProvider d2interface.FileProvider
|
||||
normalImage *ebiten.Image
|
||||
pressedImage *ebiten.Image
|
||||
toggledImage *ebiten.Image
|
||||
@ -100,7 +107,7 @@ type Button struct {
|
||||
}
|
||||
|
||||
// CreateButton creates an instance of Button
|
||||
func CreateButton(buttonType ButtonType, fileProvider common.FileProvider, text string) *Button {
|
||||
func CreateButton(buttonType ButtonType, fileProvider d2interface.FileProvider, text string) *Button {
|
||||
result := &Button{
|
||||
fileProvider: fileProvider,
|
||||
width: 0,
|
||||
@ -111,8 +118,9 @@ func CreateButton(buttonType ButtonType, fileProvider common.FileProvider, text
|
||||
}
|
||||
buttonLayout := ButtonLayouts[buttonType]
|
||||
result.buttonLayout = buttonLayout
|
||||
font := GetFont(buttonLayout.FontPath, palettedefs.Units, fileProvider)
|
||||
buttonSprite := fileProvider.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||
font := GetFont(buttonLayout.FontPath, d2enum.Units, fileProvider)
|
||||
|
||||
buttonSprite := d2render.CreateSprite(fileProvider.LoadFile(buttonLayout.ResourceName), datadict.Palettes[buttonLayout.PaletteName])
|
||||
totalButtonTypes := buttonSprite.GetTotalFrames() / (buttonLayout.XSegments * buttonLayout.YSegments)
|
||||
for i := 0; i < buttonLayout.XSegments; i++ {
|
||||
w, _ := buttonSprite.GetFrameSize(i)
|
||||
@ -179,7 +187,7 @@ func (v *Button) Draw(target *ebiten.Image) {
|
||||
|
||||
if !v.enabled {
|
||||
//opts.CompositeMode = ebiten.CompositeModeLighter
|
||||
opts.ColorM = common.ColorToColorM(color.RGBA{128, 128, 128, 195})
|
||||
opts.ColorM = d2helper.ColorToColorM(color.RGBA{128, 128, 128, 195})
|
||||
target.DrawImage(v.disabledImage, opts)
|
||||
} else if v.toggled && v.pressed {
|
||||
target.DrawImage(v.pressedToggledImage, opts)
|
@ -4,8 +4,16 @@ import (
|
||||
"image/color"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2helper"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -19,12 +27,12 @@ type FontSize struct {
|
||||
|
||||
// Font represents a font
|
||||
type Font struct {
|
||||
fontSprite *common.Sprite
|
||||
fontSprite *d2render.Sprite
|
||||
metrics map[uint8]FontSize
|
||||
}
|
||||
|
||||
// GetFont creates or loads an existing font
|
||||
func GetFont(font string, palette palettedefs.PaletteType, fileProvider common.FileProvider) *Font {
|
||||
func GetFont(font string, palette d2enum.PaletteType, fileProvider d2interface.FileProvider) *Font {
|
||||
cacheItem, exists := fontCache[font+"_"+string(palette)]
|
||||
if exists {
|
||||
return cacheItem
|
||||
@ -35,11 +43,11 @@ func GetFont(font string, palette palettedefs.PaletteType, fileProvider common.F
|
||||
}
|
||||
|
||||
// CreateFont creates an instance of a MPQ Font
|
||||
func CreateFont(font string, palette palettedefs.PaletteType, fileProvider common.FileProvider) *Font {
|
||||
func CreateFont(font string, palette d2enum.PaletteType, fileProvider d2interface.FileProvider) *Font {
|
||||
result := &Font{
|
||||
metrics: make(map[uint8]FontSize),
|
||||
}
|
||||
result.fontSprite = fileProvider.LoadSprite(font+".dc6", palette)
|
||||
result.fontSprite = d2render.CreateSprite(fileProvider.LoadFile(font+".dc6"), datadict.Palettes[palette])
|
||||
woo := "Woo!\x01"
|
||||
fontData := fileProvider.LoadFile(font + ".tbl")
|
||||
if string(fontData[0:5]) != woo {
|
||||
@ -62,12 +70,12 @@ func (v *Font) GetTextMetrics(text string) (width, height uint32) {
|
||||
height = uint32(0)
|
||||
maxCharHeight := uint32(0)
|
||||
for _, m := range v.fontSprite.Frames {
|
||||
maxCharHeight = common.Max(maxCharHeight, uint32(m.Height))
|
||||
maxCharHeight = d2helper.Max(maxCharHeight, uint32(m.Height))
|
||||
}
|
||||
for i := 0; i < len(text); i++ {
|
||||
ch := text[i]
|
||||
if ch == '\n' {
|
||||
width = common.Max(width, curWidth)
|
||||
width = d2helper.Max(width, curWidth)
|
||||
curWidth = 0
|
||||
height += maxCharHeight + 6
|
||||
continue
|
||||
@ -75,7 +83,7 @@ func (v *Font) GetTextMetrics(text string) (width, height uint32) {
|
||||
metric := v.metrics[uint8(ch)]
|
||||
curWidth += uint32(metric.Width)
|
||||
}
|
||||
width = common.Max(width, curWidth)
|
||||
width = d2helper.Max(width, curWidth)
|
||||
height += maxCharHeight
|
||||
return
|
||||
}
|
||||
@ -87,7 +95,7 @@ func (v *Font) Draw(x, y int, text string, color color.Color, target *ebiten.Ima
|
||||
|
||||
maxCharHeight := uint32(0)
|
||||
for _, m := range v.metrics {
|
||||
maxCharHeight = common.Max(maxCharHeight, uint32(m.Height))
|
||||
maxCharHeight = d2helper.Max(maxCharHeight, uint32(m.Height))
|
||||
}
|
||||
|
||||
targetWidth, _ := target.Size()
|
@ -3,8 +3,10 @@ package ui
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -34,7 +36,7 @@ type Label struct {
|
||||
}
|
||||
|
||||
// CreateLabel creates a new instance of a UI label
|
||||
func CreateLabel(provider common.FileProvider, font string, palette palettedefs.PaletteType) *Label {
|
||||
func CreateLabel(provider d2interface.FileProvider, font string, palette d2enum.PaletteType) *Label {
|
||||
result := &Label{
|
||||
Alignment: LabelAlignLeft,
|
||||
Color: color.White,
|
@ -1,10 +1,12 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -21,22 +23,22 @@ const (
|
||||
// Manager represents the UI manager
|
||||
type Manager struct {
|
||||
widgets []Widget
|
||||
cursorSprite *common.Sprite
|
||||
cursorSprite *d2render.Sprite
|
||||
cursorButtons CursorButton
|
||||
pressedIndex int
|
||||
CursorX int
|
||||
CursorY int
|
||||
clickSfx *sound.SoundEffect
|
||||
clickSfx *d2audio.SoundEffect
|
||||
waitForLeftMouseUp bool
|
||||
}
|
||||
|
||||
// CreateManager creates a new instance of a UI manager
|
||||
func CreateManager(fileProvider common.FileProvider, soundManager sound.Manager) *Manager {
|
||||
func CreateManager(fileProvider d2interface.FileProvider, soundManager d2audio.Manager) *Manager {
|
||||
result := &Manager{
|
||||
pressedIndex: -1,
|
||||
widgets: make([]Widget, 0),
|
||||
cursorSprite: fileProvider.LoadSprite(resourcepaths.CursorDefault, palettedefs.Units),
|
||||
clickSfx: soundManager.LoadSoundEffect(resourcepaths.SFXButtonClick),
|
||||
cursorSprite: d2render.CreateSprite(fileProvider.LoadFile(d2common.CursorDefault), datadict.Palettes[d2enum.Units]),
|
||||
clickSfx: soundManager.LoadSoundEffect(d2common.SFXButtonClick),
|
||||
waitForLeftMouseUp: false,
|
||||
}
|
||||
return result
|
@ -1,12 +1,12 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
// Widget defines an object that is a UI widget
|
||||
type Widget interface {
|
||||
common.Drawable
|
||||
d2interface.Drawable
|
||||
GetEnabled() bool
|
||||
SetEnabled(enabled bool)
|
||||
SetPressed(pressed bool)
|
3
go.mod
3
go.mod
@ -11,11 +11,12 @@ require (
|
||||
github.com/gopherjs/gopherwasm v1.1.0 // indirect
|
||||
github.com/hajimehoshi/ebiten v1.10.1-0.20191108205544-35436ea50457
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 // indirect
|
||||
github.com/mewspring/tools v0.0.0-20191031203036-122e7c80ae0a // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/pkg/profile v1.3.0
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 // indirect
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
|
||||
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a // indirect
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd // indirect
|
||||
golang.org/x/tools v0.0.0-20191107010934-f79515f33823 // indirect
|
||||
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101 // indirect
|
||||
)
|
||||
|
5
go.sum
5
go.sum
@ -46,6 +46,8 @@ github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2Q
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mewspring/tools v0.0.0-20191031203036-122e7c80ae0a h1:Bgb7myjG5GA2qL+rXzV1pc3lbKXVEc4NhUfciOvWp+E=
|
||||
github.com/mewspring/tools v0.0.0-20191031203036-122e7c80ae0a/go.mod h1:QEmU0TSELL2hDAiUxfPAjLuC10uK0CkvFULzHIUZ1us=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
@ -103,8 +105,11 @@ golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191026034945-b2104f82a97d h1:QFO0Wgcqcp8nI9hbisKDTBsmfwrvLswk2T73QDZZgVo=
|
||||
golang.org/x/tools v0.0.0-20191026034945-b2104f82a97d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191031220737-6d8f1af9ccc0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191107010934-f79515f33823 h1:akkRBeitX2EZP59KdtKw310CI4WGPCNPyrLbE7WZA8Y=
|
||||
golang.org/x/tools v0.0.0-20191107010934-f79515f33823/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101 h1:LCmXVkvpQCDj724eX6irUTPCJP5GelFHxqGSWL2D1R0=
|
||||
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
16
main.go
16
main.go
@ -4,12 +4,14 @@ import (
|
||||
"image"
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/scenes"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/mpq"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/mpq"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
@ -18,16 +20,17 @@ var GitBranch string
|
||||
|
||||
// GitCommit is set by the CI build process to the commit hash
|
||||
var GitCommit string
|
||||
var d2Engine *core.Engine
|
||||
var d2Engine *d2core.Engine
|
||||
|
||||
func main() {
|
||||
//defer profile.Start(profile.CPUProfile).Stop()
|
||||
//runtime.LockOSThread()
|
||||
//defer runtime.UnlockOSThread()
|
||||
if len(GitBranch) == 0 {
|
||||
GitBranch = "Local Build"
|
||||
GitCommit = ""
|
||||
}
|
||||
common.SetBuildInfo(GitBranch, GitCommit)
|
||||
d2common.SetBuildInfo(GitBranch, GitCommit)
|
||||
log.SetFlags(log.Ldate | log.LUTC | log.Lmicroseconds | log.Llongfile)
|
||||
log.Println("OpenDiablo2 - Open source Diablo 2 engine")
|
||||
_, iconImage, err := ebitenutil.NewImageFromFile("d2logo.png", ebiten.FilterLinear)
|
||||
@ -35,7 +38,8 @@ func main() {
|
||||
ebiten.SetWindowIcon([]image.Image{iconImage})
|
||||
}
|
||||
mpq.InitializeCryptoBuffer()
|
||||
d2Engine = core.CreateEngine()
|
||||
d2Engine = d2core.CreateEngine()
|
||||
d2Engine.SetNextScene(scenes.CreateMainMenu(d2Engine, d2Engine, d2Engine.UIManager, d2Engine.SoundManager))
|
||||
ebiten.SetCursorVisible(false)
|
||||
ebiten.SetFullscreen(d2Engine.Settings.FullScreen)
|
||||
ebiten.SetRunnableInBackground(d2Engine.Settings.RunInBackground)
|
||||
|
@ -1,568 +0,0 @@
|
||||
package scenes
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/palettedefs"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/resourcepaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type HeroStance int
|
||||
|
||||
const (
|
||||
HeroStanceIdle HeroStance = 0
|
||||
HeroStanceIdleSelected HeroStance = 1
|
||||
HeroStanceApproaching HeroStance = 2
|
||||
HeroStanceSelected HeroStance = 3
|
||||
HeroStanceRetreating HeroStance = 4
|
||||
)
|
||||
|
||||
type HeroRenderInfo struct {
|
||||
Stance HeroStance
|
||||
IdleSprite *common.Sprite
|
||||
IdleSelectedSprite *common.Sprite
|
||||
ForwardWalkSprite *common.Sprite
|
||||
ForwardWalkSpriteOverlay *common.Sprite
|
||||
SelectedSprite *common.Sprite
|
||||
SelectedSpriteOverlay *common.Sprite
|
||||
BackWalkSprite *common.Sprite
|
||||
BackWalkSpriteOverlay *common.Sprite
|
||||
SelectionBounds image.Rectangle
|
||||
SelectSfx *sound.SoundEffect
|
||||
DeselectSfx *sound.SoundEffect
|
||||
}
|
||||
|
||||
type SelectHeroClass struct {
|
||||
uiManager *ui.Manager
|
||||
soundManager *sound.Manager
|
||||
fileProvider common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
bgImage *common.Sprite
|
||||
campfire *common.Sprite
|
||||
headingLabel *ui.Label
|
||||
heroClassLabel *ui.Label
|
||||
heroDesc1Label *ui.Label
|
||||
heroDesc2Label *ui.Label
|
||||
heroDesc3Label *ui.Label
|
||||
heroRenderInfo map[common.Hero]*HeroRenderInfo
|
||||
selectedHero common.Hero
|
||||
exitButton *ui.Button
|
||||
}
|
||||
|
||||
func CreateSelectHeroClass(
|
||||
fileProvider common.FileProvider,
|
||||
sceneProvider SceneProvider,
|
||||
uiManager *ui.Manager, soundManager *sound.Manager,
|
||||
) *SelectHeroClass {
|
||||
result := &SelectHeroClass{
|
||||
uiManager: uiManager,
|
||||
sceneProvider: sceneProvider,
|
||||
fileProvider: fileProvider,
|
||||
soundManager: soundManager,
|
||||
heroRenderInfo: make(map[common.Hero]*HeroRenderInfo),
|
||||
selectedHero: common.HeroNone,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Load() []func() {
|
||||
v.soundManager.PlayBGM(resourcepaths.BGMTitle)
|
||||
return []func(){
|
||||
func() {
|
||||
v.bgImage = v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBackground, palettedefs.Fechar)
|
||||
v.bgImage.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.headingLabel = ui.CreateLabel(v.fileProvider, resourcepaths.Font30, palettedefs.Units)
|
||||
fontWidth, _ := v.headingLabel.GetSize()
|
||||
v.headingLabel.MoveTo(400-int(fontWidth/2), 17)
|
||||
v.headingLabel.SetText("Select Hero Class")
|
||||
v.headingLabel.Alignment = ui.LabelAlignCenter
|
||||
},
|
||||
func() {
|
||||
v.heroClassLabel = ui.CreateLabel(v.fileProvider, resourcepaths.Font30, palettedefs.Units)
|
||||
v.heroClassLabel.Alignment = ui.LabelAlignCenter
|
||||
v.heroClassLabel.MoveTo(400, 65)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc1Label = ui.CreateLabel(v.fileProvider, resourcepaths.Font16, palettedefs.Units)
|
||||
v.heroDesc1Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc1Label.MoveTo(400, 100)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc2Label = ui.CreateLabel(v.fileProvider, resourcepaths.Font16, palettedefs.Units)
|
||||
v.heroDesc2Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc2Label.MoveTo(400, 115)
|
||||
},
|
||||
func() {
|
||||
v.heroDesc3Label = ui.CreateLabel(v.fileProvider, resourcepaths.Font16, palettedefs.Units)
|
||||
v.heroDesc3Label.Alignment = ui.LabelAlignCenter
|
||||
v.heroDesc3Label.MoveTo(400, 130)
|
||||
},
|
||||
func() {
|
||||
v.campfire = v.fileProvider.LoadSprite(resourcepaths.CharacterSelectCampfire, palettedefs.Fechar)
|
||||
v.campfire.MoveTo(380, 335)
|
||||
v.campfire.Animate = true
|
||||
v.campfire.Blend = true
|
||||
},
|
||||
func() {
|
||||
v.exitButton = ui.CreateButton(ui.ButtonTypeMedium, v.fileProvider, common.TranslateString("#970"))
|
||||
v.exitButton.MoveTo(33, 537)
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitButton)
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroBarbarian] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianForwardWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianForwardWalkOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianSelected, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectBarbarianBackWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{364, 201}, Max: image.Point{90, 170}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXBarbarianSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXBarbarianDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroBarbarian].IdleSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].IdleSelectedSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSprite.SpecialFrameTime = 2500
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSpriteOverlay.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSpriteOverlay.SpecialFrameTime = 2500
|
||||
v.heroRenderInfo[common.HeroBarbarian].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].SelectedSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].BackWalkSprite.MoveTo(400, 330)
|
||||
v.heroRenderInfo[common.HeroBarbarian].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroBarbarian].BackWalkSprite.SpecialFrameTime = 1000
|
||||
v.heroRenderInfo[common.HeroBarbarian].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroSorceress] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressForwardWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressForwardWalkOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressSelected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressSelectedOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressBackWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecSorceressBackWalkOverlay, palettedefs.Fechar),
|
||||
image.Rectangle{Min: image.Point{580, 240}, Max: image.Point{65, 160}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXSorceressSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXSorceressDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroSorceress].IdleSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].IdleSelectedSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSprite.SpecialFrameTime = 2300
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSpriteOverlay.SpecialFrameTime = 2300
|
||||
v.heroRenderInfo[common.HeroSorceress].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroSorceress].SelectedSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].SelectedSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroSorceress].SelectedSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].SelectedSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSprite.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSprite.SpecialFrameTime = 1200
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSpriteOverlay.MoveTo(626, 352)
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSpriteOverlay.SpecialFrameTime = 1200
|
||||
v.heroRenderInfo[common.HeroSorceress].BackWalkSpriteOverlay.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroNecromancer] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectNecromancerUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectNecromancerUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerForwardWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerForwardWalkOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerSelected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerSelectedOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerBackWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecNecromancerBackWalkOverlay, palettedefs.Fechar),
|
||||
image.Rectangle{Min: image.Point{265, 220}, Max: image.Point{55, 175}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXNecromancerSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXNecromancerDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroNecromancer].IdleSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].IdleSelectedSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSprite.SpecialFrameTime = 2000
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSpriteOverlay.SpecialFrameTime = 2000
|
||||
v.heroRenderInfo[common.HeroNecromancer].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].SelectedSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].SelectedSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].SelectedSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].SelectedSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSprite.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSpriteOverlay.Blend = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSpriteOverlay.MoveTo(300, 335)
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSpriteOverlay.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[common.HeroNecromancer].BackWalkSpriteOverlay.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroPaladin] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectPaladinUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectPaladinUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecPaladinForwardWalk, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecPaladinForwardWalkOverlay, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecPaladinSelected, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecPaladinBackWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{490, 210}, Max: image.Point{65, 180}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXPaladinSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXPaladinDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroPaladin].IdleSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].IdleSelectedSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSprite.SpecialFrameTime = 3400
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSpriteOverlay.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSpriteOverlay.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSpriteOverlay.SpecialFrameTime = 3400
|
||||
v.heroRenderInfo[common.HeroPaladin].ForwardWalkSpriteOverlay.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroPaladin].SelectedSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].BackWalkSprite.MoveTo(521, 338)
|
||||
v.heroRenderInfo[common.HeroPaladin].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroPaladin].BackWalkSprite.SpecialFrameTime = 1300
|
||||
v.heroRenderInfo[common.HeroPaladin].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroAmazon] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAmazonUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAmazonUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecAmazonForwardWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecAmazonSelected, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelecAmazonBackWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{70, 220}, Max: image.Point{55, 200}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXAmazonSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXAmazonDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroAmazon].IdleSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[common.HeroAmazon].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAmazon].IdleSelectedSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[common.HeroAmazon].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAmazon].ForwardWalkSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[common.HeroAmazon].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAmazon].ForwardWalkSprite.SpecialFrameTime = 2200
|
||||
v.heroRenderInfo[common.HeroAmazon].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroAmazon].SelectedSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[common.HeroAmazon].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAmazon].BackWalkSprite.MoveTo(100, 339)
|
||||
v.heroRenderInfo[common.HeroAmazon].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAmazon].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[common.HeroAmazon].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroAssassin] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAssassinUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAssassinUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAssassinForwardWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAssassinSelected, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectAssassinBackWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{175, 235}, Max: image.Point{50, 180}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXAssassinSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXAssassinDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroAssassin].IdleSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[common.HeroAssassin].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAssassin].IdleSelectedSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[common.HeroAssassin].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAssassin].ForwardWalkSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[common.HeroAssassin].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAssassin].ForwardWalkSprite.SpecialFrameTime = 3800
|
||||
v.heroRenderInfo[common.HeroAssassin].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroAssassin].SelectedSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[common.HeroAssassin].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAssassin].BackWalkSprite.MoveTo(231, 365)
|
||||
v.heroRenderInfo[common.HeroAssassin].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroAssassin].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[common.HeroAssassin].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
func() {
|
||||
v.heroRenderInfo[common.HeroDruid] = &HeroRenderInfo{
|
||||
HeroStanceIdle,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectDruidUnselected, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectDruidUnselectedH, palettedefs.Fechar),
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectDruidForwardWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectDruidSelected, palettedefs.Fechar),
|
||||
nil,
|
||||
v.fileProvider.LoadSprite(resourcepaths.CharacterSelectDruidBackWalk, palettedefs.Fechar),
|
||||
nil,
|
||||
image.Rectangle{Min: image.Point{680, 220}, Max: image.Point{70, 195}},
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXDruidSelect),
|
||||
v.soundManager.LoadSoundEffect(resourcepaths.SFXDruidDeselect),
|
||||
}
|
||||
v.heroRenderInfo[common.HeroDruid].IdleSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[common.HeroDruid].IdleSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroDruid].IdleSelectedSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[common.HeroDruid].IdleSelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroDruid].ForwardWalkSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[common.HeroDruid].ForwardWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroDruid].ForwardWalkSprite.SpecialFrameTime = 4800
|
||||
v.heroRenderInfo[common.HeroDruid].ForwardWalkSprite.StopOnLastFrame = true
|
||||
v.heroRenderInfo[common.HeroDruid].SelectedSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[common.HeroDruid].SelectedSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroDruid].BackWalkSprite.MoveTo(720, 370)
|
||||
v.heroRenderInfo[common.HeroDruid].BackWalkSprite.Animate = true
|
||||
v.heroRenderInfo[common.HeroDruid].BackWalkSprite.SpecialFrameTime = 1500
|
||||
v.heroRenderInfo[common.HeroDruid].BackWalkSprite.StopOnLastFrame = true
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Unload() {
|
||||
v.heroRenderInfo = nil
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) onExitButtonClicked() {
|
||||
v.sceneProvider.SetNextScene(CreateCharacterSelect(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Render(screen *ebiten.Image) {
|
||||
v.bgImage.DrawSegments(screen, 4, 3, 0)
|
||||
v.headingLabel.Draw(screen)
|
||||
if v.selectedHero != common.HeroNone {
|
||||
v.heroClassLabel.Draw(screen)
|
||||
v.heroDesc1Label.Draw(screen)
|
||||
v.heroDesc2Label.Draw(screen)
|
||||
v.heroDesc3Label.Draw(screen)
|
||||
}
|
||||
for heroClass, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance == HeroStanceIdle || heroInfo.Stance == HeroStanceIdleSelected {
|
||||
v.renderHero(screen, heroClass)
|
||||
}
|
||||
}
|
||||
for heroClass, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance != HeroStanceIdle && heroInfo.Stance != HeroStanceIdleSelected {
|
||||
v.renderHero(screen, heroClass)
|
||||
}
|
||||
}
|
||||
v.campfire.Draw(screen)
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Update(tickTime float64) {
|
||||
canSelect := true
|
||||
for _, info := range v.heroRenderInfo {
|
||||
if info.Stance != HeroStanceIdle && info.Stance != HeroStanceIdleSelected && info.Stance != HeroStanceSelected {
|
||||
canSelect = false
|
||||
break
|
||||
}
|
||||
}
|
||||
allIdle := true
|
||||
for heroType, data := range v.heroRenderInfo {
|
||||
if allIdle && data.Stance != HeroStanceIdle {
|
||||
allIdle = false
|
||||
}
|
||||
v.updateHeroSelectionHover(heroType, canSelect)
|
||||
}
|
||||
if v.selectedHero != common.HeroNone && allIdle {
|
||||
v.selectedHero = common.HeroNone
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) updateHeroSelectionHover(hero common.Hero, canSelect bool) {
|
||||
renderInfo := v.heroRenderInfo[hero]
|
||||
switch renderInfo.Stance {
|
||||
case HeroStanceApproaching:
|
||||
if renderInfo.ForwardWalkSprite.OnLastFrame() {
|
||||
renderInfo.Stance = HeroStanceSelected
|
||||
renderInfo.SelectedSprite.ResetAnimation()
|
||||
if renderInfo.SelectedSpriteOverlay != nil {
|
||||
renderInfo.SelectedSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
}
|
||||
return
|
||||
case HeroStanceRetreating:
|
||||
if renderInfo.BackWalkSprite.OnLastFrame() {
|
||||
renderInfo.Stance = HeroStanceIdle
|
||||
renderInfo.IdleSprite.ResetAnimation()
|
||||
}
|
||||
return
|
||||
}
|
||||
if !canSelect {
|
||||
return
|
||||
}
|
||||
if renderInfo.Stance == HeroStanceSelected {
|
||||
return
|
||||
}
|
||||
mouseX := v.uiManager.CursorX
|
||||
mouseY := v.uiManager.CursorY
|
||||
b := renderInfo.SelectionBounds
|
||||
mouseHover := (mouseX >= b.Min.X) && (mouseX <= b.Min.X+b.Max.X) && (mouseY >= b.Min.Y) && (mouseY <= b.Min.Y+b.Max.Y)
|
||||
if mouseHover && v.uiManager.CursorButtonPressed(ui.CursorButtonLeft) {
|
||||
// showEntryUi = true;
|
||||
renderInfo.Stance = HeroStanceApproaching
|
||||
renderInfo.ForwardWalkSprite.ResetAnimation()
|
||||
if renderInfo.ForwardWalkSpriteOverlay != nil {
|
||||
renderInfo.ForwardWalkSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
for _, heroInfo := range v.heroRenderInfo {
|
||||
if heroInfo.Stance != HeroStanceSelected {
|
||||
continue
|
||||
}
|
||||
heroInfo.SelectSfx.Stop()
|
||||
heroInfo.DeselectSfx.Play()
|
||||
heroInfo.Stance = HeroStanceRetreating
|
||||
heroInfo.BackWalkSprite.ResetAnimation()
|
||||
if heroInfo.BackWalkSpriteOverlay != nil {
|
||||
heroInfo.BackWalkSpriteOverlay.ResetAnimation()
|
||||
}
|
||||
}
|
||||
v.selectedHero = hero
|
||||
v.updateHeroText()
|
||||
renderInfo.SelectSfx.Play()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if mouseHover {
|
||||
renderInfo.Stance = HeroStanceIdleSelected
|
||||
} else {
|
||||
renderInfo.Stance = HeroStanceIdle
|
||||
}
|
||||
|
||||
if v.selectedHero == common.HeroNone && mouseHover {
|
||||
v.selectedHero = hero
|
||||
v.updateHeroText()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) renderHero(screen *ebiten.Image, hero common.Hero) {
|
||||
renderInfo := v.heroRenderInfo[hero]
|
||||
switch renderInfo.Stance {
|
||||
case HeroStanceIdle:
|
||||
renderInfo.IdleSprite.Draw(screen)
|
||||
case HeroStanceIdleSelected:
|
||||
renderInfo.IdleSelectedSprite.Draw(screen)
|
||||
case HeroStanceApproaching:
|
||||
renderInfo.ForwardWalkSprite.Draw(screen)
|
||||
if renderInfo.ForwardWalkSpriteOverlay != nil {
|
||||
renderInfo.ForwardWalkSpriteOverlay.Draw(screen)
|
||||
}
|
||||
case HeroStanceSelected:
|
||||
renderInfo.SelectedSprite.Draw(screen)
|
||||
if renderInfo.SelectedSpriteOverlay != nil {
|
||||
renderInfo.SelectedSpriteOverlay.Draw(screen)
|
||||
}
|
||||
case HeroStanceRetreating:
|
||||
renderInfo.BackWalkSprite.Draw(screen)
|
||||
if renderInfo.BackWalkSpriteOverlay != nil {
|
||||
renderInfo.BackWalkSpriteOverlay.Draw(screen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) updateHeroText() {
|
||||
switch v.selectedHero {
|
||||
case common.HeroNone:
|
||||
return
|
||||
case common.HeroBarbarian:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharbar"))
|
||||
v.setDescLabels("#1709")
|
||||
case common.HeroNecromancer:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharnec"))
|
||||
v.setDescLabels("#1704")
|
||||
case common.HeroPaladin:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharpal"))
|
||||
v.setDescLabels("#1711")
|
||||
case common.HeroAssassin:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharass"))
|
||||
v.setDescLabels("#305")
|
||||
case common.HeroSorceress:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharsor"))
|
||||
v.setDescLabels("#1710")
|
||||
case common.HeroAmazon:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partycharama"))
|
||||
v.setDescLabels("#1698")
|
||||
case common.HeroDruid:
|
||||
v.heroClassLabel.SetText(common.TranslateString("partychardru"))
|
||||
v.setDescLabels("#304")
|
||||
}
|
||||
/*
|
||||
if (selectedHero == null)
|
||||
return;
|
||||
|
||||
switch (selectedHero.Value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
heroClassLabel.Location = new Point(400 - (heroClassLabel.TextArea.Width / 2), 65);
|
||||
heroDesc1Label.Location = new Point(400 - (heroDesc1Label.TextArea.Width / 2), 100);
|
||||
heroDesc2Label.Location = new Point(400 - (heroDesc2Label.TextArea.Width / 2), 115);
|
||||
heroDesc3Label.Location = new Point(400 - (heroDesc3Label.TextArea.Width / 2), 130);
|
||||
*/
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) setDescLabels(descKey string) {
|
||||
heroDesc := common.TranslateString(descKey)
|
||||
parts := common.SplitIntoLinesWithMaxWidth(heroDesc, 37)
|
||||
if len(parts) > 1 {
|
||||
v.heroDesc1Label.SetText(parts[0])
|
||||
} else {
|
||||
v.heroDesc1Label.SetText("")
|
||||
}
|
||||
if len(parts) > 1 {
|
||||
v.heroDesc2Label.SetText(parts[1])
|
||||
} else {
|
||||
v.heroDesc2Label.SetText("")
|
||||
}
|
||||
if len(parts) > 2 {
|
||||
v.heroDesc3Label.SetText(parts[2])
|
||||
} else {
|
||||
v.heroDesc3Label.SetText("")
|
||||
}
|
||||
}
|
@ -6,19 +6,21 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/mpq"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/mpq"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
func TestMPQScanPerformance(t *testing.T) {
|
||||
log.SetFlags(log.Ldate | log.LUTC | log.Lmicroseconds | log.Llongfile)
|
||||
mpq.InitializeCryptoBuffer()
|
||||
common.ConfigBasePath = "../"
|
||||
config := common.LoadConfiguration()
|
||||
engine := core.CreateEngine()
|
||||
d2common.ConfigBasePath = "../"
|
||||
config := d2common.LoadConfiguration()
|
||||
engine := d2core.CreateEngine()
|
||||
for _, fileName := range config.MpqLoadOrder {
|
||||
mpqFile := path.Join(config.MpqPath, fileName)
|
||||
archive, _ := mpq.Load(mpqFile)
|
||||
@ -34,12 +36,12 @@ func TestMPQScanPerformance(t *testing.T) {
|
||||
parts := strings.Split(archiveFile, ".")
|
||||
switch strings.ToLower(parts[len(parts)-1]) {
|
||||
case "coff":
|
||||
_ = common.LoadCof(archiveFile, engine)
|
||||
_ = d2data.LoadCof(archiveFile, engine)
|
||||
case "dcc":
|
||||
if strings.ContainsAny(archiveFile, "common") {
|
||||
continue
|
||||
}
|
||||
_ = common.LoadDCC(archiveFile, engine)
|
||||
_ = d2data.LoadDCC(archiveFile, engine)
|
||||
}
|
||||
|
||||
_, _ = archive.ReadFile(archiveFile)
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
|
||||
_map "github.com/OpenDiablo2/OpenDiablo2/map"
|
||||
_map "github.com/OpenDiablo2/OpenDiablo2/d2render/mapengine"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/mpq"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2data/mpq"
|
||||
)
|
||||
|
||||
func TestMapGenerationPerformance(t *testing.T) {
|
||||
mpq.InitializeCryptoBuffer()
|
||||
common.ConfigBasePath = "../"
|
||||
d2common.ConfigBasePath = "../"
|
||||
|
||||
engine := core.CreateEngine()
|
||||
gameState := common.CreateGameState()
|
||||
engine := d2core.CreateEngine()
|
||||
gameState := d2core.CreateGameState()
|
||||
mapEngine := _map.CreateMapEngine(gameState, engine.SoundManager, engine)
|
||||
mapEngine.GenerateAct1Overworld()
|
||||
surface, _ := ebiten.NewImage(800, 600, ebiten.FilterNearest)
|
||||
|
Loading…
Reference in New Issue
Block a user