lint fixes (#615)

This commit is contained in:
Gürkan Kaymak 2020-07-23 19:56:50 +03:00 committed by GitHub
parent 80e655964e
commit 7a49f3637f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 504 additions and 428 deletions

View File

@ -17,6 +17,10 @@ import (
"strings"
"sync"
"github.com/pkg/profile"
"golang.org/x/image/colornames"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
@ -32,9 +36,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
"github.com/OpenDiablo2/OpenDiablo2/d2script"
"github.com/pkg/profile"
"golang.org/x/image/colornames"
"gopkg.in/alecthomas/kingpin.v2"
)
// App represents the main application for the engine
@ -91,7 +92,7 @@ func Create(gitBranch, gitCommit string,
}
// Run executes the application and kicks off the entire game process
func (p *App) Run() error {
func (a *App) Run() error {
profileOption := kingpin.Flag("profile", "Profiles the program, one of (cpu, mem, block, goroutine, trace, thread, mutex)").String()
kingpin.Parse()
@ -102,88 +103,86 @@ func (p *App) Run() error {
}
}
windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", p.gitBranch)
windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", a.gitBranch)
// If we fail to initialize, we will show the error screen
if err := p.initialize(); err != nil {
if gameErr := p.renderer.Run(updateInitError, 800, 600, windowTitle); gameErr != nil {
if err := a.initialize(); err != nil {
if gameErr := a.renderer.Run(updateInitError, 800, 600, windowTitle); gameErr != nil {
return gameErr
}
return err
}
p.ToMainMenu()
a.ToMainMenu()
if p.gitBranch == "" {
p.gitBranch = "Local Build"
if a.gitBranch == "" {
a.gitBranch = "Local Build"
}
d2common.SetBuildInfo(p.gitBranch, p.gitCommit)
if err := p.renderer.Run(p.update, 800, 600, windowTitle); err != nil {
if err := a.renderer.Run(a.update, 800, 600, windowTitle); err != nil {
return err
}
return nil
}
func (p *App) initialize() error {
p.timeScale = 1.0
p.lastTime = d2common.Now()
p.lastScreenAdvance = p.lastTime
func (a *App) initialize() error {
a.timeScale = 1.0
a.lastTime = d2common.Now()
a.lastScreenAdvance = a.lastTime
p.renderer.SetWindowIcon("d2logo.png")
p.terminal.BindLogger()
a.renderer.SetWindowIcon("d2logo.png")
a.terminal.BindLogger()
terminalActions := [...]bindTerminalEntry{
{"dumpheap", "dumps the heap to pprof/heap.pprof", p.dumpHeap},
{"fullscreen", "toggles fullscreen", p.toggleFullScreen},
{"capframe", "captures a still frame", p.captureFrame},
{"capgifstart", "captures an animation (start)", p.startAnimationCapture},
{"capgifstop", "captures an animation (stop)", p.stopAnimationCapture},
{"vsync", "toggles vsync", p.toggleVsync},
{"fps", "toggle fps counter", p.toggleFpsCounter},
{"timescale", "set scalar for elapsed time", p.setTimeScale},
{"quit", "exits the game", p.quitGame},
{"screen-gui", "enters the gui playground screen", p.enterGuiPlayground},
{"js", "eval JS scripts", p.evalJS},
{"dumpheap", "dumps the heap to pprof/heap.pprof", a.dumpHeap},
{"fullscreen", "toggles fullscreen", a.toggleFullScreen},
{"capframe", "captures a still frame", a.captureFrame},
{"capgifstart", "captures an animation (start)", a.startAnimationCapture},
{"capgifstop", "captures an animation (stop)", a.stopAnimationCapture},
{"vsync", "toggles vsync", a.toggleVsync},
{"fps", "toggle fps counter", a.toggleFpsCounter},
{"timescale", "set scalar for elapsed time", a.setTimeScale},
{"quit", "exits the game", a.quitGame},
{"screen-gui", "enters the gui playground screen", a.enterGuiPlayground},
{"js", "eval JS scripts", a.evalJS},
}
for idx := range terminalActions {
action := &terminalActions[idx]
if err := p.terminal.BindAction(action.name, action.description, action.action); err != nil {
if err := a.terminal.BindAction(action.name, action.description, action.action); err != nil {
log.Fatal(err)
}
}
if err := d2asset.Initialize(p.renderer, p.terminal); err != nil {
if err := d2asset.Initialize(a.renderer, a.terminal); err != nil {
return err
}
if err := d2gui.Initialize(p.inputManager); err != nil {
if err := d2gui.Initialize(a.inputManager); err != nil {
return err
}
config := d2config.Config
p.audio.SetVolumes(config.BgmVolume, config.SfxVolume)
a.audio.SetVolumes(config.BgmVolume, config.SfxVolume)
if err := p.loadDataDict(); err != nil {
if err := a.loadDataDict(); err != nil {
return err
}
if err := p.loadStrings(); err != nil {
if err := a.loadStrings(); err != nil {
return err
}
d2inventory.LoadHeroObjects()
d2ui.Initialize(p.inputManager, p.audio)
d2ui.Initialize(a.inputManager, a.audio)
return nil
}
func (p *App) loadStrings() error {
func (a *App) loadStrings() error {
tablePaths := []string{
d2resource.PatchStringTable,
d2resource.ExpansionStringTable,
@ -202,7 +201,7 @@ func (p *App) loadStrings() error {
return nil
}
func (p *App) loadDataDict() error {
func (a *App) loadDataDict() error {
entries := []struct {
path string
loader func(data []byte)
@ -256,14 +255,14 @@ func (p *App) loadDataDict() error {
return nil
}
func (p *App) renderDebug(target d2interface.Surface) error {
if !p.showFPS {
func (a *App) renderDebug(target d2interface.Surface) error {
if !a.showFPS {
return nil
}
vsyncEnabled := p.renderer.GetVSyncEnabled()
fps := p.renderer.CurrentFPS()
cx, cy := p.renderer.GetCursorPos()
vsyncEnabled := a.renderer.GetVSyncEnabled()
fps := a.renderer.CurrentFPS()
cx, cy := a.renderer.GetCursorPos()
target.PushTranslation(5, 565)
target.DrawTextf("vsync:" + strconv.FormatBool(vsyncEnabled) + "\nFPS:" + strconv.Itoa(int(fps)))
@ -275,7 +274,7 @@ func (p *App) renderDebug(target d2interface.Surface) error {
target.PushTranslation(680, 0)
target.DrawTextf("Alloc " + strconv.FormatInt(int64(m.Alloc)/bytesToMegabyte, 10))
target.PushTranslation(0, 16)
target.DrawTextf("TAlloc/s " + strconv.FormatFloat(p.allocRate(m.TotalAlloc, fps), 'f', 2, 64))
target.DrawTextf("TAlloc/s " + strconv.FormatFloat(a.allocRate(m.TotalAlloc, fps), 'f', 2, 64))
target.PushTranslation(0, 16)
target.DrawTextf("Pause " + strconv.FormatInt(int64(m.PauseTotalNs/bytesToMegabyte), 10))
target.PushTranslation(0, 16)
@ -289,18 +288,18 @@ func (p *App) renderDebug(target d2interface.Surface) error {
return nil
}
func (p *App) renderCapture(target d2interface.Surface) error {
func (a *App) renderCapture(target d2interface.Surface) error {
cleanupCapture := func() {
p.captureState = captureStateNone
p.capturePath = ""
p.captureFrames = nil
a.captureState = captureStateNone
a.capturePath = ""
a.captureFrames = nil
}
switch p.captureState {
switch a.captureState {
case captureStateFrame:
defer cleanupCapture()
fp, err := os.Create(p.capturePath)
fp, err := os.Create(a.capturePath)
if err != nil {
return err
}
@ -316,15 +315,15 @@ func (p *App) renderCapture(target d2interface.Surface) error {
return err
}
log.Printf("saved frame to %s", p.capturePath)
log.Printf("saved frame to %s", a.capturePath)
case captureStateGif:
screenshot := target.Screenshot()
p.captureFrames = append(p.captureFrames, screenshot)
a.captureFrames = append(a.captureFrames, screenshot)
case captureStateNone:
if len(p.captureFrames) > 0 {
if len(a.captureFrames) > 0 {
defer cleanupCapture()
fp, err := os.Create(p.capturePath)
fp, err := os.Create(a.capturePath)
if err != nil {
return err
}
@ -336,7 +335,7 @@ func (p *App) renderCapture(target d2interface.Surface) error {
}()
var (
framesTotal = len(p.captureFrames)
framesTotal = len(a.captureFrames)
framesPal = make([]*image.Paletted, framesTotal)
frameDelays = make([]int, framesTotal)
framesPerCPU = framesTotal / runtime.NumCPU()
@ -352,7 +351,7 @@ func (p *App) renderCapture(target d2interface.Surface) error {
for j := start; j < end; j++ {
var buffer bytes.Buffer
if err := gif.Encode(&buffer, p.captureFrames[j], nil); err != nil {
if err := gif.Encode(&buffer, a.captureFrames[j], nil); err != nil {
panic(err)
}
@ -373,14 +372,14 @@ func (p *App) renderCapture(target d2interface.Surface) error {
return err
}
log.Printf("saved animation to %s", p.capturePath)
log.Printf("saved animation to %s", a.capturePath)
}
}
return nil
}
func (p *App) render(target d2interface.Surface) error {
func (a *App) render(target d2interface.Surface) error {
if err := d2screen.Render(target); err != nil {
return err
}
@ -391,26 +390,26 @@ func (p *App) render(target d2interface.Surface) error {
return err
}
if err := p.renderDebug(target); err != nil {
if err := a.renderDebug(target); err != nil {
return err
}
if err := p.renderCapture(target); err != nil {
if err := a.renderCapture(target); err != nil {
return err
}
if err := p.terminal.Render(target); err != nil {
if err := a.terminal.Render(target); err != nil {
return err
}
return nil
}
func (p *App) advance(elapsed, current float64) error {
elapsedLastScreenAdvance := (current - p.lastScreenAdvance) * p.timeScale
func (a *App) advance(elapsed, current float64) error {
elapsedLastScreenAdvance := (current - a.lastScreenAdvance) * a.timeScale
if elapsedLastScreenAdvance > defaultFPS {
p.lastScreenAdvance = current
a.lastScreenAdvance = current
if err := d2screen.Advance(elapsedLastScreenAdvance); err != nil {
return err
@ -419,7 +418,7 @@ func (p *App) advance(elapsed, current float64) error {
d2ui.Advance(elapsed)
if err := p.inputManager.Advance(elapsed, current); err != nil {
if err := a.inputManager.Advance(elapsed, current); err != nil {
return err
}
@ -427,23 +426,23 @@ func (p *App) advance(elapsed, current float64) error {
return err
}
if err := p.terminal.Advance(elapsed); err != nil {
if err := a.terminal.Advance(elapsed); err != nil {
return err
}
return nil
}
func (p *App) update(target d2interface.Surface) error {
func (a *App) update(target d2interface.Surface) error {
currentTime := d2common.Now()
elapsedTime := (currentTime - p.lastTime) * p.timeScale
p.lastTime = currentTime
elapsedTime := (currentTime - a.lastTime) * a.timeScale
a.lastTime = currentTime
if err := p.advance(elapsedTime, currentTime); err != nil {
if err := a.advance(elapsedTime, currentTime); err != nil {
return err
}
if err := p.render(target); err != nil {
if err := a.render(target); err != nil {
return err
}
@ -454,15 +453,15 @@ func (p *App) update(target d2interface.Surface) error {
return nil
}
func (p *App) allocRate(totalAlloc uint64, fps float64) float64 {
p.tAllocSamples.Value = totalAlloc
p.tAllocSamples = p.tAllocSamples.Next()
deltaAllocPerFrame := float64(totalAlloc-p.tAllocSamples.Value.(uint64)) / nSamplesTAlloc
func (a *App) allocRate(totalAlloc uint64, fps float64) float64 {
a.tAllocSamples.Value = totalAlloc
a.tAllocSamples = a.tAllocSamples.Next()
deltaAllocPerFrame := float64(totalAlloc-a.tAllocSamples.Value.(uint64)) / nSamplesTAlloc
return deltaAllocPerFrame * fps / bytesToMegabyte
}
func (p *App) dumpHeap() {
func (a *App) dumpHeap() {
if err := os.Mkdir("./pprof/", 0750); err != nil {
log.Fatal(err)
}
@ -478,64 +477,64 @@ func (p *App) dumpHeap() {
}
}
func (p *App) evalJS(code string) {
val, err := p.scriptEngine.Eval(code)
func (a *App) evalJS(code string) {
val, err := a.scriptEngine.Eval(code)
if err != nil {
p.terminal.OutputErrorf("%s", err)
a.terminal.OutputErrorf("%s", err)
return
}
log.Printf("%s", val)
}
func (p *App) toggleFullScreen() {
fullscreen := !p.renderer.IsFullScreen()
p.renderer.SetFullScreen(fullscreen)
p.terminal.OutputInfof("fullscreen is now: %v", fullscreen)
func (a *App) toggleFullScreen() {
fullscreen := !a.renderer.IsFullScreen()
a.renderer.SetFullScreen(fullscreen)
a.terminal.OutputInfof("fullscreen is now: %v", fullscreen)
}
func (p *App) captureFrame(path string) {
p.captureState = captureStateFrame
p.capturePath = path
p.captureFrames = nil
func (a *App) captureFrame(path string) {
a.captureState = captureStateFrame
a.capturePath = path
a.captureFrames = nil
}
func (p *App) startAnimationCapture(path string) {
p.captureState = captureStateGif
p.capturePath = path
p.captureFrames = nil
func (a *App) startAnimationCapture(path string) {
a.captureState = captureStateGif
a.capturePath = path
a.captureFrames = nil
}
func (p *App) stopAnimationCapture() {
p.captureState = captureStateNone
func (a *App) stopAnimationCapture() {
a.captureState = captureStateNone
}
func (p *App) toggleVsync() {
vsync := !p.renderer.GetVSyncEnabled()
p.renderer.SetVSyncEnabled(vsync)
p.terminal.OutputInfof("vsync is now: %v", vsync)
func (a *App) toggleVsync() {
vsync := !a.renderer.GetVSyncEnabled()
a.renderer.SetVSyncEnabled(vsync)
a.terminal.OutputInfof("vsync is now: %v", vsync)
}
func (p *App) toggleFpsCounter() {
p.showFPS = !p.showFPS
p.terminal.OutputInfof("fps counter is now: %v", p.showFPS)
func (a *App) toggleFpsCounter() {
a.showFPS = !a.showFPS
a.terminal.OutputInfof("fps counter is now: %v", a.showFPS)
}
func (p *App) setTimeScale(timeScale float64) {
func (a *App) setTimeScale(timeScale float64) {
if timeScale <= 0 {
p.terminal.OutputErrorf("invalid time scale value")
a.terminal.OutputErrorf("invalid time scale value")
} else {
p.terminal.OutputInfof("timescale changed from %f to %f", p.timeScale, timeScale)
p.timeScale = timeScale
a.terminal.OutputInfof("timescale changed from %f to %f", a.timeScale, timeScale)
a.timeScale = timeScale
}
}
func (p *App) quitGame() {
func (a *App) quitGame() {
os.Exit(0)
}
func (p *App) enterGuiPlayground() {
d2screen.SetNextScreen(d2gamescreen.CreateGuiTestMain(p.renderer))
func (a *App) enterGuiPlayground() {
d2screen.SetNextScreen(d2gamescreen.CreateGuiTestMain(a.renderer))
}
func createZeroedRing(n int) *ring.Ring {
@ -604,7 +603,7 @@ func updateInitError(target d2interface.Surface) error {
}
func (a *App) ToMainMenu() {
mainMenu := d2gamescreen.CreateMainMenu(a, a.renderer, a.inputManager, a.audio)
mainMenu := d2gamescreen.CreateMainMenu(a, a.renderer, a.inputManager, a.audio, d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit})
mainMenu.SetScreenMode(d2gamescreen.ScreenModeMainMenu)
d2screen.SetNextScreen(mainMenu)
}

View File

@ -9,7 +9,7 @@ import (
var _ d2interface.BitStream = &BitStream{} // Static check to confirm struct conforms to interface
const (
maxBits = 16
maxBits = 16
bitsPerByte = 8
)

View File

@ -1,20 +0,0 @@
package d2common
// BuildInfoRecord is the structure used to hold information about the current build
type BuildInfoRecord struct {
// Branch is the branch this build is based on (or 'Local' if built locally)
Branch string
// Commit is the commit hash of the build (or blank if built locally)
Commit string
}
// BuildInfo contains information about the build currently being ran
var BuildInfo BuildInfoRecord
// SetBuildInfo is called at the start of the application to generate the global BuildInfo value
func SetBuildInfo(branch, commit string) {
BuildInfo = BuildInfoRecord{
Branch: branch,
Commit: commit,
}
}

View File

@ -96,7 +96,7 @@ func LoadHireling(file []byte) {
hireling := &HirelingRecord{
Hireling: d.String("Hireling"),
SubType: d.String("SubType"),
ID: d.Number("Id"),
ID: d.Number("ID"),
Class: d.Number("Class"),
Act: d.Number("Act"),
Difficulty: d.Number("Difficulty"),
@ -109,7 +109,7 @@ func LoadHireling(file []byte) {
HP: d.Number("HP"),
HPPerLvl: d.Number("HP/Lvl"),
Defense: d.Number("Defense"),
DefPerLvl: d.Number("Id"),
DefPerLvl: d.Number("ID"),
Str: d.Number("Str"),
StrPerLvl: d.Number("Str/Lvl"),
Dex: d.Number("Dex"),

View File

@ -36,7 +36,7 @@ func LoadLevelWarps(file []byte) {
for d.Next() {
record := &LevelWarpRecord{
Name: d.String("Name"),
ID: d.Number("Id"),
ID: d.Number("ID"),
SelectX: d.Number("SelectX"),
SelectY: d.Number("SelectY"),
SelectDX: d.Number("SelectDX"),

View File

@ -74,7 +74,7 @@ type LevelDetailsRecord struct {
MonsterUniqueID9 string // umon9
MonsterUniqueID10 string // umon10
// Critter Species 1-4. Uses the Id from monstats2.txt and only monsters
// Critter Species 1-4. Uses the ID from monstats2.txt and only monsters
// with critter column set to 1 can spawn here. critter column is also found
// in monstats2.txt. Critters are in reality only present clientside.
MonsterCritterID1 string // cmon1
@ -93,9 +93,9 @@ type LevelDetailsRecord struct {
// present in the expension folders)
TitleImageName string // EntryFile
// Id
// ID
// Level ID (used in columns like VIS0-7)
Id int //nolint:golint,stylecheck // Id is the right key
Id int //nolint:golint,stylecheck // ID is the right key
// Palette is the Act Palette . Reference only
Palette int // Pal
@ -138,7 +138,7 @@ type LevelDetailsRecord struct {
// location.
DependantLevelID int // Depend
// The type of the Level (Id from lvltypes.txt)
// The type of the Level (ID from lvltypes.txt)
LevelType int // LevelType
// Controls if teleport is allowed in that level.
@ -367,7 +367,7 @@ type LevelDetailsRecord struct {
//nolint:gochecknoglobals // Currently global by design, only written once
var LevelDetails map[int]*LevelDetailsRecord
// GetLevelDetails gets a LevelDetailsRecord by the record Id
// GetLevelDetails gets a LevelDetailsRecord by the record ID
func GetLevelDetails(id int) *LevelDetailsRecord {
for i := 0; i < len(LevelDetails); i++ {
if LevelDetails[i].Id == id {
@ -387,7 +387,7 @@ func LoadLevelDetails(file []byte) {
for d.Next() {
record := &LevelDetailsRecord{
Name: d.String("Name "),
Id: d.Number("Id"),
Id: d.Number("ID"),
Palette: d.Number("Pal"),
Act: d.Number("Act"),
QuestFlag: d.Number("QuestFlag"),

View File

@ -110,7 +110,7 @@ type MissileRecord struct {
ExplosionMissile string // name of a missile from missiles.txt that is created upon collision
// or anytime it is destroyed if AlwaysExplode is true
Id int //nolint:golint,stylecheck // Id is the correct key
Id int //nolint:golint,stylecheck // ID is the correct key
ClientMovementFunc int
ClientCollisionFunc int

View File

@ -17,9 +17,9 @@ type (
// Key contains the pointer that will be used in other txt files
// such as levels.txt and superuniques.txt.
Key string // called `Id` in monstats.txt
Key string // called `ID` in monstats.txt
// Id is the actual internal ID of the unit (this is what the ID pointer
// ID is the actual internal ID of the unit (this is what the ID pointer
// actually points at) remember that no two units can have the same ID,
// this will result in lots of unpredictable behavior and crashes so please
// dont do it. This 'HarcCodedInDeX' is used for several things, such as
@ -80,10 +80,10 @@ type (
// which animation mode will the spawned monster be spawned in.
SpawnAnimationKey string // called `spawnmode` in monstats.txt
// MinionId1 is an Id of a minion that spawns when this monster is created
// MinionId1 is an ID of a minion that spawns when this monster is created
MinionId1 string //nolint:golint,stylecheck // called `minion1` in monstats.txt
// MinionId2 is an Id of a minion that spawns when this monster is created
// MinionId2 is an ID of a minion that spawns when this monster is created
MinionId2 string //nolint:golint,stylecheck // called `minion2` in monstats.txt
// SoundKeyNormal, SoundKeySpecial
@ -690,7 +690,7 @@ func LoadMonStats(file []byte) { // nolint:funlen // Makes no sense to split
d := d2common.LoadDataDictionary(file)
for d.Next() {
record := &MonStatsRecord{
Key: d.String("Id"),
Key: d.String("ID"),
Id: d.Number("hcIdx"),
BaseKey: d.String("BaseId"),
NextKey: d.String("NextInClass"),

View File

@ -177,7 +177,7 @@ func LoadMonStats2(file []byte) {
d := d2common.LoadDataDictionary(file)
for d.Next() {
record := &MonStats2Record{
Key: d.String("Id"),
Key: d.String("ID"),
Height: d.Number("Height"),
OverlayHeight: d.Number("OverlayHeight"),
PixelHeight: d.Number("pixHeight"),

View File

@ -10,11 +10,11 @@ import (
type ObjectLookupRecord struct {
Act int
Type d2enum.ObjectType
Id int //nolint:golint,stylecheck // Id is the right key
Id int //nolint:golint,stylecheck // ID is the right key
Name string
Description string
ObjectsTxtId int //nolint:golint,stylecheck // Id is the right key
MonstatsTxtId int //nolint:golint,stylecheck // Id is the right key
ObjectsTxtId int //nolint:golint,stylecheck // ID is the right key
MonstatsTxtId int //nolint:golint,stylecheck // ID is the right key
Direction int
Base string
Token string
@ -44,7 +44,7 @@ type ObjectLookupRecord struct {
func LookupObject(act, typ, id int) *ObjectLookupRecord {
object := lookupObject(act, typ, id, indexedObjects)
if object == nil {
log.Panicf("Failed to look up object Act: %d, Type: %d, Id: %d", act, typ, id)
log.Panicf("Failed to look up object Act: %d, Type: %d, ID: %d", act, typ, id)
}
return object
@ -96,6 +96,6 @@ func indexObjects(objects []ObjectLookupRecord) [][][]*ObjectLookupRecord {
// IndexedObjects is a slice of object records for quick lookups.
// nil checks should be done for uninitialized values at each level.
// [Act 1-5][Type 1-2][Id 0-855]
// [Act 1-5][Type 1-2][ID 0-855]
//nolint:gochecknoglobals // Currently global by design
var indexedObjects [][][]*ObjectLookupRecord

View File

@ -281,7 +281,7 @@ func LoadSkills(file []byte) {
for d.Next() {
record := &SkillRecord{
Skill: d.String("skill"),
ID: d.Number("Id"),
ID: d.Number("ID"),
Charclass: d.String("charclass"),
Skilldesc: d.String("skilldesc"),
Srvstfunc: d.Number("srvstfunc"),

View File

@ -22,7 +22,7 @@ type SuperUniqueRecord struct {
// Name for this SuperUnique which must be retrieved from a .TBL file
Name string
// the base monster type of the SuperUnique, refers to the "Key" field in monstats.go ("Id" column in the MonStats.txt)
// the base monster type of the SuperUnique, refers to the "Key" field in monstats.go ("ID" column in the MonStats.txt)
Class string
// This is the "hardcoded index".
@ -39,7 +39,7 @@ type SuperUniqueRecord struct {
MonSound string
// These three fields assign special abilities so SuperUnique monsters such as "Fire Enchanted" or "Stone Skin".
// These fields refers to the Id's corresponding to the properties in MonUMod.txt.
// These fields refers to the ID's corresponding to the properties in MonUMod.txt.
// Here is the list of available properties.
// 0. None
// 1. Inits the random name seed, automatically added to monster, you don't need to add this UMod.

View File

@ -6,10 +6,10 @@ import (
// Object is a game world object
type Object struct {
Type int
Id int //nolint:golint Id is the right key
X int
Y int
Flags int
Paths []d2common.Path
Type int
Id int //nolint:golint ID is the right key
X int
Y int
Flags int
Paths []d2common.Path
}

View File

@ -1,6 +1,6 @@
package d2enum
// RegionIdType represents a region Id
// RegionIdType represents a region ID
type RegionIdType int //nolint:golint,stylecheck // many changed needed when changing to ID
// Regions

View File

@ -78,17 +78,17 @@ func (rn *RangedNumber) Add(other *RangedNumber) *RangedNumber {
// Sub subtracts the given ranged number from this one, returning this one
func (rn *RangedNumber) Sub(other *RangedNumber) *RangedNumber {
return rn.Set(rn.min - other.min, rn.max - other.max)
return rn.Set(rn.min-other.min, rn.max-other.max)
}
// Mul multiplies this ranged number by the given ranged number, returning this one
func (rn *RangedNumber) Mul(other *RangedNumber) *RangedNumber {
return rn.Set(rn.min * other.min, rn.max * other.max)
return rn.Set(rn.min*other.min, rn.max*other.max)
}
// Div divides this ranged number by the given ranged number, returning this one
func (rn *RangedNumber) Div(other *RangedNumber) *RangedNumber {
return rn.Set(rn.min / other.min, rn.max / other.max)
return rn.Set(rn.min/other.min, rn.max/other.max)
}
func (rn *RangedNumber) String() string {
@ -98,4 +98,3 @@ func (rn *RangedNumber) String() string {
return fmt.Sprintf("%d to %d", rn.min, rn.max)
}

View File

@ -287,6 +287,7 @@ func (a *animation) SetPlayLength(playLength float64) {
func (a *animation) SetPlayLengthMs(playLengthMs int) {
// TODO remove this method
const millisecondsPerSecond = 1000.0
a.SetPlayLength(float64(playLengthMs) / millisecondsPerSecond)
}

View File

@ -138,7 +138,9 @@ func (c *Composite) SetDirection(direction int) {
for layerIdx := range c.mode.layers {
layer := c.mode.layers[layerIdx]
if layer != nil {
layer.SetDirection(c.direction)
if err := layer.SetDirection(c.direction); err != nil {
fmt.Printf("failed to set direction of layer: %d, err: %v\n", layerIdx, err)
}
}
}
}
@ -182,7 +184,9 @@ func (c *Composite) SetCurrentFrame(frame int) {
for layerIdx := range c.mode.layers {
layer := c.mode.layers[layerIdx]
if layer != nil {
layer.SetCurrentFrame(frame)
if err := layer.SetCurrentFrame(frame); err != nil {
fmt.Printf("failed to set current frame of layer: %d, err: %v\n", layerIdx, err)
}
}
}
}

View File

@ -26,19 +26,17 @@ func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string,
return nil, err
}
animation := animation{
directions: make([]animationDirection, dc6.Directions),
playLength: defaultPlayLength,
playLoop: true,
originAtBottom: true,
effect: effect,
}
anim := DC6Animation{
animation: animation,
dc6Path: dc6Path,
palette: palette,
renderer: renderer,
animation: animation{
directions: make([]animationDirection, dc6.Directions),
playLength: defaultPlayLength,
playLoop: true,
originAtBottom: true,
effect: effect,
},
dc6Path: dc6Path,
palette: palette,
renderer: renderer,
}
err = anim.SetDirection(0)

View File

@ -21,7 +21,7 @@ type DCCAnimation struct {
renderer d2iface.Renderer
}
// CreateAnimationFromDCC creates an animation from d2dcc.DCC and d2dat.DATPalette
// CreateDCCAnimation creates an animation from d2dcc.DCC and d2dat.DATPalette
func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2iface.Palette,
effect d2enum.DrawEffect) (d2iface.Animation, error) {
dcc, err := loadDCC(dccPath)

View File

@ -3,10 +3,11 @@ package ebiten
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/hajimehoshi/ebiten/audio"
"github.com/hajimehoshi/ebiten/audio/wav"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
// SoundEffect represents an ebiten implementation of a sound effect

View File

@ -2,9 +2,10 @@
package ebiten
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/inpututil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
)
var (

View File

@ -31,21 +31,18 @@ type MapEngine struct {
dt1Files []string // List of DS1 strings
}
// CreateMapEngine creates a new instance of the map engine and
// returns a pointer to it.
// CreateMapEngine creates a new instance of the map engine and returns a pointer to it.
func CreateMapEngine() *MapEngine {
engine := &MapEngine{}
return engine
}
// GetStartingPosition returns the starting position on the map in
// sub-tiles.
func (m *MapEngine) GetStartingPosition() (int, int) {
// GetStartingPosition returns the starting position on the map in sub-tiles.
func (m *MapEngine) GetStartingPosition() (x, y int) {
return m.startSubTileX, m.startSubTileY
}
// ResetMap clears all map and entity data and reloads it from the
// cached files.
// ResetMap clears all map and entity data and reloads it from the cached files.
func (m *MapEngine) ResetMap(levelType d2enum.RegionIdType, width, height int) {
m.entities = make([]d2interface.MapEntity, 0)
m.levelType = d2datadict.LevelTypes[levelType]
@ -176,8 +173,8 @@ func (m *MapEngine) tileCoordinateToIndex(x, y int) int {
}
// converts tile index from MapEngine.tiles to x,y coordinate
func (m *MapEngine) tileIndexToCoordinate(index int) (int, int) {
return (index % m.size.Width), (index / m.size.Width)
func (m *MapEngine) tileIndexToCoordinate(index int) (x, y int) {
return index % m.size.Width, index / m.size.Width
}
// SubTileAt gets the flags for the given subtile
@ -224,7 +221,7 @@ func (m *MapEngine) RemoveEntity(entity d2interface.MapEntity) {
// GetTiles returns a slice of all tiles matching the given style,
// sequence and tileType.
func (m *MapEngine) GetTiles(style, sequence, tileType int) []d2dt1.Tile {
var tiles []d2dt1.Tile
tiles := make([]d2dt1.Tile, 0, len(m.dt1TileData))
for idx := range m.dt1TileData {
if m.dt1TileData[idx].Style != int32(style) || m.dt1TileData[idx].Sequence != int32(sequence) ||
@ -244,7 +241,7 @@ func (m *MapEngine) GetTiles(style, sequence, tileType int) []d2dt1.Tile {
}
// GetStartPosition returns the spawn point on entering the current map.
func (m *MapEngine) GetStartPosition() (float64, float64) {
func (m *MapEngine) GetStartPosition() (x, y float64) {
for tileY := 0; tileY < m.size.Height; tileY++ {
for tileX := 0; tileX < m.size.Width; tileX++ {
tile := m.tiles[tileX+(tileY*m.size.Width)].Components
@ -260,7 +257,7 @@ func (m *MapEngine) GetStartPosition() (float64, float64) {
}
// GetCenterPosition returns the center point of the map.
func (m *MapEngine) GetCenterPosition() (float64, float64) {
func (m *MapEngine) GetCenterPosition() (x, y float64) {
return float64(m.size.Width) / 2.0, float64(m.size.Height) / 2.0
}
@ -290,7 +287,7 @@ func (m *MapEngine) TileExists(tileX, tileY int) bool {
}
// GenerateMap clears the map and places the specified stamp.
func (m *MapEngine) GenerateMap(regionType d2enum.RegionIdType, levelPreset int, fileIndex int, cacheTiles bool) {
func (m *MapEngine) GenerateMap(regionType d2enum.RegionIdType, levelPreset, fileIndex int) {
region := d2mapstamp.LoadStamp(regionType, levelPreset, fileIndex)
regionSize := region.Size()
m.ResetMap(regionType, regionSize.Width, regionSize.Height)

View File

@ -79,11 +79,9 @@ func (t *MapTile) PrepareTile(x, y int, me *MapEngine) {
}
}
// Walker's Alias Method for weighted random selection with xorshifting for random numbers
// Selects a random tile from the slice, rest of args just used for seeding
func getRandomTile(tiles []d2dt1.Tile, x, y int, seed int64) byte {
/* Walker's Alias Method for weighted random selection
* with xorshifting for random numbers */
var tileSeed uint64
tileSeed = uint64(seed) + uint64(x)
tileSeed *= uint64(y)

View File

@ -6,6 +6,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
)
// PathFind finds a path between given start and dest positions and returns the positions of the path
func (m *MapEngine) PathFind(start, dest d2vector.Position) []d2vector.Position {
points := make([]d2vector.Position, 0)
_, point := m.checkLos(start, dest)

View File

@ -1,6 +1,8 @@
package d2mapentity
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)
@ -34,7 +36,10 @@ func (ae *AnimatedEntity) Render(target d2interface.Surface) {
)
defer target.Pop()
ae.animation.Render(target)
if err := ae.animation.Render(target); err != nil {
fmt.Printf("failed to render animated entity, err: %v\n", err)
}
}
// GetDirection returns the current facing direction of this entity.
@ -46,11 +51,15 @@ func (ae *AnimatedEntity) GetDirection() int {
func (ae *AnimatedEntity) rotate(direction int) {
ae.direction = direction
ae.animation.SetDirection(ae.direction)
if err := ae.animation.SetDirection(ae.direction); err != nil {
fmt.Printf("failed to update the animation direction, err: %v\n", err)
}
}
// Advance is called once per frame and processes a
// single game tick.
func (ae *AnimatedEntity) Advance(elapsed float64) {
ae.animation.Advance(elapsed)
if err := ae.animation.Advance(elapsed); err != nil {
fmt.Printf("failed to advance the animation, err: %v\n", err)
}
}

View File

@ -2,7 +2,6 @@ package d2mapentity
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
)
// mapEntity represents an entity on the map that can be animated

View File

@ -19,10 +19,12 @@ type Missile struct {
record *d2datadict.MissileRecord
}
// GetPosition returns the position of the missile
func (m *Missile) GetPosition() d2vector.Position {
return m.AnimatedEntity.Position
}
// GetVelocity returns the velocity vector of the missile
func (m *Missile) GetVelocity() d2vector.Vector {
return m.AnimatedEntity.velocity
}
@ -42,7 +44,6 @@ func CreateMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error)
}
animation.SetEffect(d2enum.DrawEffectModulate)
// animation.SetPlaySpeed(float64(record.Animation.AnimationSpeed))
animation.SetPlayLoop(record.Animation.LoopAnimation)
animation.PlayForward()
entity := CreateAnimatedEntity(x, y, animation)

View File

@ -1,7 +1,6 @@
package d2mapentity
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"math/rand"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -9,6 +8,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)

View File

@ -1,6 +1,8 @@
package d2mapentity
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -14,19 +16,21 @@ import (
// Player is the player character entity.
type Player struct {
mapEntity
composite *d2asset.Composite
Equipment *d2inventory.CharacterEquipment
Stats *d2hero.HeroStatsState
Class d2enum.Hero
Id string
name string
// nameLabel d2ui.Label
ID string
name string
animationMode string
composite *d2asset.Composite
Equipment *d2inventory.CharacterEquipment
Stats *d2hero.HeroStatsState
Class d2enum.Hero
lastPathSize int
isInTown bool
animationMode string
isRunToggled bool
isRunning bool
isCasting bool
// nameLabel d2ui.Label
}
// run speed should be walkspeed * 1.5, since in the original game it is 6 yards walk and 9 yards run.
@ -34,7 +38,7 @@ const baseWalkSpeed = 6.0
const baseRunSpeed = 9.0
// CreatePlayer creates a new player entity and returns a pointer to it.
func CreatePlayer(id, name string, x, y int, direction int, heroType d2enum.Hero,
func CreatePlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
stats *d2hero.HeroStatsState, equipment *d2inventory.CharacterEquipment) *Player {
layerEquipment := &[d2enum.CompositeTypeMax]string{
d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(),
@ -57,7 +61,7 @@ func CreatePlayer(id, name string, x, y int, direction int, heroType d2enum.Hero
stats.Stamina = stats.MaxStamina
result := &Player{
Id: id,
ID: id,
mapEntity: newMapEntity(x, y),
composite: composite,
Equipment: equipment,
@ -71,16 +75,17 @@ func CreatePlayer(id, name string, x, y int, direction int, heroType d2enum.Hero
}
result.SetSpeed(baseRunSpeed)
result.mapEntity.directioner = result.rotate
//result.nameLabel.Alignment = d2ui.LabelAlignCenter
//result.nameLabel.SetText(name)
//result.nameLabel.Color = color.White
err = composite.SetMode(d2enum.PlayerAnimationModeTownNeutral, equipment.RightHand.GetWeaponClass())
if err != nil {
panic(err)
}
composite.SetDirection(direction)
composite.Equip(layerEquipment)
if err := composite.Equip(layerEquipment); err != nil {
fmt.Printf("failed to equip, err: %v\n", err)
}
return result
}
@ -119,64 +124,69 @@ func (p *Player) SetIsRunning(isRunning bool) {
}
// IsInTown returns true if the player is currently in town.
func (p Player) IsInTown() bool {
func (p *Player) IsInTown() bool {
return p.isInTown
}
// Advance is called once per frame and processes a
// single game tick.
func (v *Player) Advance(tickTime float64) {
v.Step(tickTime)
func (p *Player) Advance(tickTime float64) {
p.Step(tickTime)
if v.IsCasting() && v.composite.GetPlayedCount() >= 1 {
v.isCasting = false
v.SetAnimationMode(v.GetAnimationMode())
}
v.composite.Advance(tickTime)
if v.lastPathSize != len(v.path) {
v.lastPathSize = len(v.path)
if p.IsCasting() && p.composite.GetPlayedCount() >= 1 {
p.isCasting = false
if err := p.SetAnimationMode(p.GetAnimationMode()); err != nil {
fmt.Printf("failed to set animationMode to: %d, err: %v\n", p.GetAnimationMode(), err)
}
}
if v.composite.GetAnimationMode() != v.animationMode {
v.animationMode = v.composite.GetAnimationMode()
if err := p.composite.Advance(tickTime); err != nil {
fmt.Printf("failed to advance composite animation of player: %s, err: %v\n", p.ID, err)
}
if p.lastPathSize != len(p.path) {
p.lastPathSize = len(p.path)
}
if p.composite.GetAnimationMode() != p.animationMode {
p.animationMode = p.composite.GetAnimationMode()
}
}
// Render renders the animated composite for this entity.
func (v *Player) Render(target d2interface.Surface) {
renderOffset := v.Position.RenderOffset()
func (p *Player) Render(target d2interface.Surface) {
renderOffset := p.Position.RenderOffset()
target.PushTranslation(
int((renderOffset.X()-renderOffset.Y())*16),
int(((renderOffset.X()+renderOffset.Y())*8)-5),
)
defer target.Pop()
v.composite.Render(target)
// v.nameLabel.X = v.offsetX
// v.nameLabel.Y = v.offsetY - 100
// v.nameLabel.Render(target)
if err := p.composite.Render(target); err != nil {
fmt.Printf("failed to render the composite of player: %s, err: %v\n", p.ID, err)
}
}
// GetAnimationMode returns the current animation mode based on what the player is doing and where they are.
func (v *Player) GetAnimationMode() d2enum.PlayerAnimationMode {
if v.IsRunning() && !v.atTarget() {
func (p *Player) GetAnimationMode() d2enum.PlayerAnimationMode {
if p.IsRunning() && !p.atTarget() {
return d2enum.PlayerAnimationModeRun
}
if v.IsInTown() {
if !v.atTarget() {
if p.IsInTown() {
if !p.atTarget() {
return d2enum.PlayerAnimationModeTownWalk
}
return d2enum.PlayerAnimationModeTownNeutral
}
if !v.atTarget() {
if !p.atTarget() {
return d2enum.PlayerAnimationModeWalk
}
if v.IsCasting() {
if p.IsCasting() {
return d2enum.PlayerAnimationModeCast
}
@ -184,44 +194,48 @@ func (v *Player) GetAnimationMode() d2enum.PlayerAnimationMode {
}
// SetAnimationMode sets the Composite's animation mode weapon class and direction.
func (v *Player) SetAnimationMode(animationMode d2enum.PlayerAnimationMode) error {
return v.composite.SetMode(animationMode, v.composite.GetWeaponClass())
func (p *Player) SetAnimationMode(animationMode d2enum.PlayerAnimationMode) error {
return p.composite.SetMode(animationMode, p.composite.GetWeaponClass())
}
// rotate sets direction and changes animation
func (v *Player) rotate(direction int) {
newAnimationMode := v.GetAnimationMode()
func (p *Player) rotate(direction int) {
newAnimationMode := p.GetAnimationMode()
if newAnimationMode.String() != v.composite.GetAnimationMode() {
v.composite.SetMode(newAnimationMode, v.composite.GetWeaponClass())
if newAnimationMode.String() != p.composite.GetAnimationMode() {
if err := p.composite.SetMode(newAnimationMode, p.composite.GetWeaponClass()); err != nil {
fmt.Printf("failed to update animationMode of %s, err: %v\n", p.composite.GetWeaponClass(), err)
}
}
if direction != v.composite.GetDirection() {
v.composite.SetDirection(direction)
if direction != p.composite.GetDirection() {
p.composite.SetDirection(direction)
}
}
// Name returns the player name.
func (v *Player) Name() string {
return v.name
func (p *Player) Name() string {
return p.name
}
// IsCasting returns true if
func (v *Player) IsCasting() bool {
return v.isCasting
func (p *Player) IsCasting() bool {
return p.isCasting
}
// SetCasting sets a flag indicating the player is casting a skill and
// sets the animation mode to the casting animation.
func (v *Player) SetCasting() {
v.isCasting = true
v.SetAnimationMode(d2enum.PlayerAnimationModeCast)
func (p *Player) SetCasting() {
p.isCasting = true
if err := p.SetAnimationMode(d2enum.PlayerAnimationModeCast); err != nil {
fmt.Printf("failed to set animationMode of player: %s to: %d, err: %v\n", p.ID, d2enum.PlayerAnimationModeCast, err)
}
}
// Selectable returns true if the player is in town.
func (v *Player) Selectable() bool {
func (p *Player) Selectable() bool {
// Players are selectable when in town
return v.IsInTown()
return p.IsInTown()
}
// GetPosition returns the entity's position

View File

@ -23,12 +23,13 @@ func (c *Camera) SetTarget(target *d2vector.Position) {
c.target = target
}
// MoveBy adds the given vector to the current position of the Camera.
// MoveTargetBy adds the given vector to the current position of the Camera.
func (c *Camera) MoveTargetBy(vector *d2vector.Vector) {
if c.target == nil {
v := c.position.Clone()
c.target = &d2vector.Position{v}
c.target = &d2vector.Position{Vector: v}
}
c.target.Add(vector)
}

View File

@ -2,6 +2,7 @@ package d2maprenderer
import (
"errors"
"fmt"
"image/color"
"log"
"math"
@ -43,14 +44,23 @@ func CreateMapRenderer(renderer d2interface.Renderer, mapEngine *d2mapengine.Map
result.Camera.position = &startPosition
result.viewport.SetCamera(&result.Camera)
term.BindAction("mapdebugvis", "set map debug visualization level", func(level int) {
var err error
err = term.BindAction("mapdebugvis", "set map debug visualization level", func(level int) {
result.mapDebugVisLevel = level
})
term.BindAction("entitydebugvis", "set entity debug visualization level", func(level int) {
if err != nil {
fmt.Printf("could not bind the mapdebugvis action, err: %v\n", err)
}
err = term.BindAction("entitydebugvis", "set entity debug visualization level", func(level int) {
result.entityDebugVisLevel = level
})
if err != nil {
fmt.Printf("could not bind the entitydebugvis action, err: %v\n", err)
}
if mapEngine.LevelType().ID != 0 {
result.generateTileCache()
}
@ -122,18 +132,18 @@ func (mr *MapRenderer) MoveCameraTargetBy(vector *d2vector.Vector) {
}
// ScreenToWorld returns the world position for the given screen (pixel) position.
func (mr *MapRenderer) ScreenToWorld(x, y int) (float64, float64) {
func (mr *MapRenderer) ScreenToWorld(x, y int) (worldX, worldY float64) {
return mr.viewport.ScreenToWorld(x, y)
}
// ScreenToOrtho returns the orthogonal position, without accounting for the isometric angle, for the given screen
// (pixel) position.
func (mr *MapRenderer) ScreenToOrtho(x, y int) (float64, float64) {
func (mr *MapRenderer) ScreenToOrtho(x, y int) (orthoX, orthoY float64) {
return mr.viewport.ScreenToOrtho(x, y)
}
// WorldToOrtho returns the orthogonal position for the given isometric world position.
func (mr *MapRenderer) WorldToOrtho(x, y float64) (float64, float64) {
func (mr *MapRenderer) WorldToOrtho(x, y float64) (orthoX, orthoY float64) {
return mr.viewport.WorldToOrtho(x, y)
}
@ -278,7 +288,9 @@ func (mr *MapRenderer) renderFloor(tile d2ds1.FloorShadowRecord, target d2interf
target.PushTranslation(mr.viewport.GetTranslationScreen())
defer target.Pop()
target.Render(img)
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the floor, err: %v\n", err)
}
}
func (mr *MapRenderer) renderWall(tile d2ds1.WallRecord, viewport *Viewport, target d2interface.Surface) {
@ -294,7 +306,9 @@ func (mr *MapRenderer) renderWall(tile d2ds1.WallRecord, viewport *Viewport, tar
target.PushTranslation(viewport.GetTranslationScreen())
defer target.Pop()
target.Render(img)
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the wall, err: %v\n", err)
}
}
func (mr *MapRenderer) renderShadow(tile d2ds1.FloorShadowRecord, target d2interface.Surface) {
@ -311,7 +325,9 @@ func (mr *MapRenderer) renderShadow(tile d2ds1.FloorShadowRecord, target d2inter
defer target.PopN(2)
target.Render(img)
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the shadow, err: %v\n", err)
}
}
func (mr *MapRenderer) renderMapDebug(mapDebugVisLevel int, target d2interface.Surface, startX, startY, endX, endY int) {
@ -333,7 +349,6 @@ func (mr *MapRenderer) renderEntityDebug(target d2interface.Surface) {
x, y := world.X()/5, world.Y()/5
velocity := e.GetVelocity()
velocity = velocity.Clone()
// velocity.Scale(60) // arbitrary scale value, just to make it easy to see
vx, vy := mr.viewport.WorldToOrtho(velocity.X(), velocity.Y())
screenX, screenY := mr.viewport.WorldToScreen(x, y)
@ -355,16 +370,16 @@ func (mr *MapRenderer) renderEntityDebug(target d2interface.Surface) {
}
// WorldToScreen returns the screen (pixel) position for the given isometric world position as two ints.
func (mr *MapRenderer) WorldToScreen(x, y float64) (int, int) {
func (mr *MapRenderer) WorldToScreen(x, y float64) (screenX, screenY int) {
return mr.viewport.WorldToScreen(x, y)
}
// WorldToScreenF returns the screen (pixel) position for the given isometric world position as two float64s.
func (mr *MapRenderer) WorldToScreenF(x, y float64) (float64, float64) {
func (mr *MapRenderer) WorldToScreenF(x, y float64) (screenX, screenY float64) {
return mr.viewport.WorldToScreenF(x, y)
}
func (mr *MapRenderer) renderTileDebug(ax, ay int, debugVisLevel int, target d2interface.Surface) {
func (mr *MapRenderer) renderTileDebug(ax, ay, debugVisLevel int, target d2interface.Surface) {
subTileColor := color.RGBA{R: 80, G: 80, B: 255, A: 50}
tileColor := color.RGBA{R: 255, G: 255, B: 255, A: 100}
tileCollisionColor := color.RGBA{R: 128, G: 0, B: 0, A: 100}
@ -398,12 +413,6 @@ func (mr *MapRenderer) renderTileDebug(ax, ay int, debugVisLevel int, target d2i
tile := mr.mapEngine.TileAt(ax, ay)
/*for i, floor := range tile.Floors {
target.PushTranslation(-20, 10+(i+1)*14)
target.DrawTextf("f: %v-%v", floor.Style, floor.Sequence)
target.Pop()
}*/
for i, wall := range tile.Components.Walls {
if wall.Type.Special() {
target.PushTranslation(-20, 10+(i+1)*14)

View File

@ -12,33 +12,32 @@ import (
func (mr *MapRenderer) generateTileCache() {
mr.palette, _ = loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
mapEngineSize := mr.mapEngine.Size()
for idx, tile := range *mr.mapEngine.Tiles() {
tileX := idx % mapEngineSize.Width
tileY := (idx - tileX) / mapEngineSize.Width
tiles := *mr.mapEngine.Tiles()
for idx := range tiles {
tile := &tiles[idx]
for i := range tile.Components.Floors {
if !tile.Components.Floors[i].Hidden && tile.Components.Floors[i].Prop1 != 0 {
mr.generateFloorCache(&tile.Components.Floors[i], tileX, tileY)
mr.generateFloorCache(&tile.Components.Floors[i])
}
}
for i := range tile.Components.Shadows {
if !tile.Components.Shadows[i].Hidden && tile.Components.Shadows[i].Prop1 != 0 {
mr.generateShadowCache(&tile.Components.Shadows[i], tileX, tileY)
mr.generateShadowCache(&tile.Components.Shadows[i])
}
}
for i := range tile.Components.Walls {
if !tile.Components.Walls[i].Hidden && tile.Components.Walls[i].Prop1 != 0 {
mr.generateWallCache(&tile.Components.Walls[i], tileX, tileY)
mr.generateWallCache(&tile.Components.Walls[i])
}
}
}
}
func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord, tileX, tileY int) {
func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), 0)
var tileData []*d2dt1.Tile
@ -93,17 +92,17 @@ func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord, tileX,
}
}
func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord, tileX, tileY int) {
func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), 13)
var tileData *d2dt1.Tile
if tileOptions == nil {
return
} else {
tileData = &tileOptions[tile.RandomIndex]
}
tileData = &tileOptions[tile.RandomIndex]
if tileData.Width == 0 || tileData.Height == 0 {
return
}
@ -133,7 +132,7 @@ func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord, tileX,
mr.setImageCacheRecord(tile.Style, tile.Sequence, 13, tile.RandomIndex, image)
}
func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord, tileX, tileY int) {
func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), int(tile.Type))
var tileData *d2dt1.Tile
@ -167,7 +166,6 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord, tileX, tileY in
realHeight := d2common.MaxInt32(d2common.AbsInt32(tileData.Height), tileMaxY-tileMinY)
tileYOffset := -tileMinY
/*tileHeight := int(tileMaxY - tileMinY)*/
if tile.Type == 15 {
tile.YAdjust = -int(tileData.RoofHeight)

View File

@ -52,61 +52,61 @@ func (v *Viewport) SetCamera(camera *Camera) {
}
// WorldToScreen returns the screen space for the given world coordinates as two integers.
func (v *Viewport) WorldToScreen(x, y float64) (int, int) {
func (v *Viewport) WorldToScreen(x, y float64) (screenX, screenY int) {
return v.OrthoToScreen(v.WorldToOrtho(x, y))
}
// WorldToScreenF returns the screen space for the given world coordinates as two float64s.
func (v *Viewport) WorldToScreenF(x, y float64) (float64, float64) {
func (v *Viewport) WorldToScreenF(x, y float64) (screenX, screenY float64) {
return v.OrthoToScreenF(v.WorldToOrtho(x, y))
}
// ScreenToWorld returns the world position for the given screen coordinates.
func (v *Viewport) ScreenToWorld(x, y int) (float64, float64) {
func (v *Viewport) ScreenToWorld(x, y int) (worldX, worldY float64) {
return v.OrthoToWorld(v.ScreenToOrtho(x, y))
}
// OrthoToWorld returns the world position for the given orthogonal coordinates.
func (v *Viewport) OrthoToWorld(x, y float64) (float64, float64) {
worldX := (x/80 + y/40) / 2
worldY := (y/40 - x/80) / 2
func (v *Viewport) OrthoToWorld(x, y float64) (worldX, worldY float64) {
worldX = (x/80 + y/40) / 2
worldY = (y/40 - x/80) / 2
return worldX, worldY
}
// WorldToOrtho returns the orthogonal position for the given world coordinates.
func (v *Viewport) WorldToOrtho(x, y float64) (float64, float64) {
orthoX := (x - y) * 80
orthoY := (x + y) * 40
func (v *Viewport) WorldToOrtho(x, y float64) (orthoX, orthoY float64) {
orthoX = (x - y) * 80
orthoY = (x + y) * 40
return orthoX, orthoY
}
// ScreenToOrtho returns the orthogonal position for the given screen coordinates.
func (v *Viewport) ScreenToOrtho(x, y int) (float64, float64) {
func (v *Viewport) ScreenToOrtho(x, y int) (orthoX, orthoY float64) {
camX, camY := v.getCameraOffset()
screenX := float64(x) + camX - float64(v.screenRect.Left)
screenY := float64(y) + camY - float64(v.screenRect.Top)
orthoX = float64(x) + camX - float64(v.screenRect.Left)
orthoY = float64(y) + camY - float64(v.screenRect.Top)
return orthoX, orthoY
}
// OrthoToScreen returns the screen position for the given orthogonal coordinates as two ints.
func (v *Viewport) OrthoToScreen(x, y float64) (screenX, screenY int) {
camOrthoX, camOrthoY := v.getCameraOffset()
screenX = int(math.Floor(x - camOrthoX + float64(v.screenRect.Left)))
screenY = int(math.Floor(y - camOrthoY + float64(v.screenRect.Top)))
return screenX, screenY
}
// OrthoToScreen returns the screen position for the given orthogonal coordinates as two ints.
func (v *Viewport) OrthoToScreen(x, y float64) (int, int) {
camOrthoX, camOrthoY := v.getCameraOffset()
orthoX := int(math.Floor(x - camOrthoX + float64(v.screenRect.Left)))
orthoY := int(math.Floor(y - camOrthoY + float64(v.screenRect.Top)))
return orthoX, orthoY
}
// OrthoToScreenF returns the screen position for the given orthogonal coordinates as two float64s.
func (v *Viewport) OrthoToScreenF(x, y float64) (float64, float64) {
func (v *Viewport) OrthoToScreenF(x, y float64) (screenX, screenY float64) {
camOrthoX, camOrthoY := v.getCameraOffset()
orthoX := x - camOrthoX + float64(v.screenRect.Left)
orthoY := y - camOrthoY + float64(v.screenRect.Top)
screenX = x - camOrthoX + float64(v.screenRect.Left)
screenY = y - camOrthoY + float64(v.screenRect.Top)
return orthoX, orthoY
return screenX, screenY
}
// IsTileVisible returns false if no part of the tile is within the game screen.
@ -136,12 +136,12 @@ func (v *Viewport) IsOrthoRectVisible(x1, y1, x2, y2 float64) bool {
}
// GetTranslationOrtho returns the viewport's current orthogonal space translation.
func (v *Viewport) GetTranslationOrtho() (float64, float64) {
func (v *Viewport) GetTranslationOrtho() (orthoX, orthoY float64) {
return v.transCurrent.x, v.transCurrent.y
}
// GetTranslationScreen returns the viewport's current screen space translation.
func (v *Viewport) GetTranslationScreen() (int, int) {
func (v *Viewport) GetTranslationScreen() (screenX, screenY int) {
return v.OrthoToScreen(v.transCurrent.x, v.transCurrent.y)
}
@ -175,8 +175,7 @@ func (v *Viewport) PopTranslation() {
v.transStack = v.transStack[:count-1]
}
func (v *Viewport) getCameraOffset() (float64, float64) {
var camX, camY float64
func (v *Viewport) getCameraOffset() (camX, camY float64) {
if v.camera != nil {
camPosition := v.camera.GetPosition()
camX, camY = camPosition.X(), camPosition.Y()

View File

@ -3,11 +3,12 @@ package ebiten
import (
"image"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
)
const (

View File

@ -6,11 +6,12 @@ import (
"image/color"
"math"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2DebugUtil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
)
const (

View File

@ -56,14 +56,18 @@ func Advance(elapsed float64) error {
if !ok {
log.Println("loadingState chan should not be closed while in a loading screen")
}
if load.err != nil {
log.Printf("PROBLEM LOADING THE SCREEN: %v", load.err)
return load.err
}
d2gui.ShowLoadScreen(load.progress)
if load.done {
singleton.currentScreen = singleton.loadingScreen
singleton.loadingScreen = nil
d2gui.ShowCursor()
d2gui.HideLoadScreen()
}
@ -80,17 +84,21 @@ func Advance(elapsed float64) error {
if handler, ok := singleton.nextScreen.(ScreenLoadHandler); ok {
d2gui.ShowLoadScreen(0)
d2gui.HideCursor()
singleton.loadingState = LoadingState{updates: make(chan loadingUpdate)}
go func() {
handler.OnLoad(singleton.loadingState)
singleton.loadingState.Done()
}()
singleton.currentScreen = nil
singleton.loadingScreen = singleton.nextScreen
} else {
singleton.currentScreen = singleton.nextScreen
singleton.loadingScreen = nil
}
singleton.nextScreen = nil
case singleton.currentScreen != nil:
if handler, ok := singleton.currentScreen.(ScreenAdvanceHandler); ok {
@ -119,6 +127,8 @@ type LoadingState struct {
updates chan loadingUpdate
}
const progressCompleted = 1.0
type loadingUpdate struct {
progress float64
err error
@ -137,6 +147,6 @@ func (l *LoadingState) Progress(ratio float64) {
// Done provides a way for callers to report that screen loading has been completed.
func (l *LoadingState) Done() {
l.updates <- loadingUpdate{progress: 1.0}
l.updates <- loadingUpdate{progress: progressCompleted}
l.updates <- loadingUpdate{done: true}
}

View File

@ -26,11 +26,11 @@ const (
)
const (
darkGrey = 0x2e3436b0
darkGrey = 0x2e3436b0
lightGrey = 0x555753b0
lightBlue = 0x3465a4b0
yellow = 0xfce94fb0
red = 0xcc0000b0
yellow = 0xfce94fb0
red = 0xcc0000b0
)
type termVis int
@ -496,7 +496,7 @@ func rgbaColor(rgba uint32) color.RGBA {
byteWidth := 8
byteMask := 0xff
for idx :=0; idx < 4; idx ++ {
for idx := 0; idx < 4; idx++ {
shift := idx * byteWidth
component := uint8(rgba>>shift) & uint8(byteMask)

View File

@ -1,10 +1,12 @@
package d2ui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"fmt"
"image"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
@ -14,6 +16,7 @@ import (
// ButtonType defines the type of button
type ButtonType int
// ButtonType constants
const (
ButtonTypeWide ButtonType = 1
ButtonTypeMedium ButtonType = 2
@ -42,64 +45,59 @@ const (
// ButtonLayout defines the type of buttons
type ButtonLayout struct {
XSegments int // 1
YSegments int // 1
ResourceName string // Font Name
PaletteName string // PaletteType
Toggleable bool // false
BaseFrame int // 0
DisabledFrame int // -1
FontPath string // ResourcePaths.FontExocet10
ClickableRect *image.Rectangle // nil
AllowFrameChange bool // true
TextOffset int // 0
ResourceName string
PaletteName string
FontPath string
XSegments int
YSegments int
BaseFrame int
DisabledFrame int
ClickableRect *image.Rectangle
TextOffset int
Toggleable bool
AllowFrameChange bool
}
// ButtonLayouts define the type of buttons you can have
var ButtonLayouts = map[ButtonType]ButtonLayout{
ButtonTypeWide: {2, 1, d2resource.WideButtonBlank, d2resource.PaletteUnits, false, 0, -1, d2resource.FontExocet10, nil, true, 1},
ButtonTypeShort: {1, 1, d2resource.ShortButtonBlank, d2resource.PaletteUnits, false, 0, -1, d2resource.FontRediculous, nil, true, -1},
ButtonTypeMedium: {1, 1, d2resource.MediumButtonBlank, d2resource.PaletteUnits, false, 0, 0, d2resource.FontExocet10, nil, true, 0},
ButtonTypeTall: {1, 1, d2resource.TallButtonBlank, d2resource.PaletteUnits, false, 0, 0, d2resource.FontExocet10, nil, true, 5},
ButtonTypeOkCancel: {1, 1, d2resource.CancelButton, d2resource.PaletteUnits, false, 0, -1, d2resource.FontRediculous, nil, true, 0},
ButtonTypeRun: {1, 1, d2resource.RunButton, d2resource.PaletteSky, true, 0, -1, d2resource.FontRediculous, nil, true, 0},
/*
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = PaletteDefs.Units } },
{eButtonType.Narrow, new ButtonLayout { ResourceName = ResourcePaths.NarrowButtonBlank, PaletteName = PaletteDefs.Units } },
{eButtonType.Cancel, new ButtonLayout { ResourceName = ResourcePaths.CancelButton, PaletteName = PaletteDefs.Units } },
// Minipanel
{eButtonType.MinipanelCharacter, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 0 } },
{eButtonType.MinipanelInventory, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 2 } },
{eButtonType.MinipanelSkill, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 4 } },
{eButtonType.MinipanelAutomap, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 8 } },
{eButtonType.MinipanelMessage, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 10 } },
{eButtonType.MinipanelQuest, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 12 } },
{eButtonType.MinipanelMenu, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = PaletteDefs.Units, BaseFrame = 14 } },
{eButtonType.SecondaryInvHand, new ButtonLayout { ResourceName = ResourcePaths.InventoryWeaponsTab, PaletteName = PaletteDefs.Units, ClickableRect = new Rectangle(0, 0, 0, 20), AllowFrameChange = false } },
{eButtonType.Run, new ButtonLayout { ResourceName = ResourcePaths.RunButton, PaletteName = PaletteDefs.Units, Toggleable = true } },
{eButtonType.Menu, new ButtonLayout { ResourceName = ResourcePaths.MenuButton, PaletteName = PaletteDefs.Units, Toggleable = true } },
{eButtonType.GoldCoin, new ButtonLayout { ResourceName = ResourcePaths.GoldCoinButton, PaletteName = PaletteDefs.Units } },
{eButtonType.Close, new ButtonLayout { ResourceName = ResourcePaths.SquareButton, PaletteName = PaletteDefs.Units, BaseFrame = 10 } },
{eButtonType.Skill, new ButtonLayout { ResourceName = ResourcePaths.AddSkillButton, PaletteName = PaletteDefs.Units, DisabledFrame = 2
*/
func getButtonLayouts() map[ButtonType]ButtonLayout {
return map[ButtonType]ButtonLayout{
ButtonTypeWide: {
XSegments: 2, YSegments: 1, ResourceName: d2resource.WideButtonBlank, PaletteName: d2resource.PaletteUnits,
DisabledFrame: -1, FontPath: d2resource.FontExocet10, AllowFrameChange: true, TextOffset: 1},
ButtonTypeShort: {
XSegments: 1, YSegments: 1, ResourceName: d2resource.ShortButtonBlank, PaletteName: d2resource.PaletteUnits,
DisabledFrame: -1, FontPath: d2resource.FontRediculous, AllowFrameChange: true, TextOffset: -1},
ButtonTypeMedium: {
XSegments: 1, YSegments: 1, ResourceName: d2resource.MediumButtonBlank, PaletteName: d2resource.PaletteUnits,
FontPath: d2resource.FontExocet10, AllowFrameChange: true},
ButtonTypeTall: {
XSegments: 1, YSegments: 1, ResourceName: d2resource.TallButtonBlank, PaletteName: d2resource.PaletteUnits,
FontPath: d2resource.FontExocet10, AllowFrameChange: true, TextOffset: 5},
ButtonTypeOkCancel: {
XSegments: 1, YSegments: 1, ResourceName: d2resource.CancelButton, PaletteName: d2resource.PaletteUnits,
DisabledFrame: -1, FontPath: d2resource.FontRediculous, AllowFrameChange: true},
ButtonTypeRun: {
XSegments: 1, YSegments: 1, ResourceName: d2resource.RunButton, PaletteName: d2resource.PaletteSky,
Toggleable: true, DisabledFrame: -1, FontPath: d2resource.FontRediculous, AllowFrameChange: true},
}
}
// Button defines a standard wide UI button
type Button struct {
enabled bool
x, y int
width, height int
visible bool
pressed bool
toggled bool
buttonLayout ButtonLayout
normalSurface d2interface.Surface
pressedSurface d2interface.Surface
toggledSurface d2interface.Surface
pressedToggledSurface d2interface.Surface
disabledSurface d2interface.Surface
buttonLayout ButtonLayout
x int
y int
width int
height int
onClick func()
enabled bool
visible bool
pressed bool
toggled bool
}
// CreateButton creates an instance of Button
@ -111,68 +109,102 @@ func CreateButton(renderer d2interface.Renderer, buttonType ButtonType, text str
enabled: true,
pressed: false,
}
buttonLayout := ButtonLayouts[buttonType]
buttonLayout := getButtonLayouts()[buttonType]
result.buttonLayout = buttonLayout
lbl := CreateLabel(buttonLayout.FontPath, d2resource.PaletteUnits)
lbl := CreateLabel(buttonLayout.FontPath, d2resource.PaletteUnits)
lbl.SetText(text)
lbl.Color = color.RGBA{R: 100, G: 100, B: 100, A: 255}
lbl.Alignment = d2gui.HorizontalAlignCenter
animation, _ := d2asset.LoadAnimation(buttonLayout.ResourceName, buttonLayout.PaletteName)
buttonSprite, _ := LoadSprite(animation)
totalButtonTypes := buttonSprite.GetFrameCount() / (buttonLayout.XSegments * buttonLayout.YSegments)
for i := 0; i < buttonLayout.XSegments; i++ {
w, _, _ := buttonSprite.GetFrameSize(i)
result.width += w
}
for i := 0; i < buttonLayout.YSegments; i++ {
_, h, _ := buttonSprite.GetFrameSize(i * buttonLayout.YSegments)
result.height += h
}
result.normalSurface, _ = renderer.NewSurface(result.width, result.height, d2enum.FilterNearest)
_, labelHeight := lbl.GetSize()
textY := result.height / 2 - labelHeight / 2
xOffset := result.width / 2
buttonSprite.SetPosition(0, 0)
buttonSprite.SetEffect(d2enum.DrawEffectModulate)
buttonSprite.RenderSegmented(result.normalSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
lbl.SetPosition(xOffset, textY)
lbl.Render(result.normalSurface)
result.renderFrames(renderer, buttonSprite, &buttonLayout, &lbl)
return result
}
func (v *Button) renderFrames(renderer d2interface.Renderer, buttonSprite *Sprite, buttonLayout *ButtonLayout, label *Label) {
totalButtonTypes := buttonSprite.GetFrameCount() / (buttonLayout.XSegments * buttonLayout.YSegments)
var err error
err = buttonSprite.RenderSegmented(v.normalSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
if err != nil {
fmt.Printf("failed to render button normalSurface, err: %v\n", err)
}
_, labelHeight := label.GetSize()
textY := v.height/2 - labelHeight/2
xOffset := v.width / 2
label.SetPosition(xOffset, textY)
label.Render(v.normalSurface)
if buttonLayout.AllowFrameChange {
if totalButtonTypes > 1 {
result.pressedSurface, _ = renderer.NewSurface(result.width, result.height, d2enum.FilterNearest)
buttonSprite.RenderSegmented(result.pressedSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+1)
v.pressedSurface, _ = renderer.NewSurface(v.width, v.height, d2enum.FilterNearest)
err = buttonSprite.RenderSegmented(v.pressedSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+1)
lbl.SetPosition(xOffset-2, textY + 2)
lbl.Render(result.pressedSurface)
if err != nil {
fmt.Printf("failed to render button pressedSurface, err: %v\n", err)
}
label.SetPosition(xOffset-2, textY+2)
label.Render(v.pressedSurface)
}
if totalButtonTypes > 2 {
result.toggledSurface, _ = renderer.NewSurface(result.width, result.height, d2enum.FilterNearest)
buttonSprite.RenderSegmented(result.toggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+2)
v.toggledSurface, _ = renderer.NewSurface(v.width, v.height, d2enum.FilterNearest)
err = buttonSprite.RenderSegmented(v.toggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+2)
lbl.SetPosition(xOffset, textY)
lbl.Render(result.toggledSurface)
if err != nil {
fmt.Printf("failed to render button toggledSurface, err: %v\n", err)
}
label.SetPosition(xOffset, textY)
label.Render(v.toggledSurface)
}
if totalButtonTypes > 3 {
result.pressedToggledSurface, _ = renderer.NewSurface(result.width, result.height, d2enum.FilterNearest)
buttonSprite.RenderSegmented(result.pressedToggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+3)
v.pressedToggledSurface, _ = renderer.NewSurface(v.width, v.height, d2enum.FilterNearest)
err = buttonSprite.RenderSegmented(v.pressedToggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+3)
lbl.SetPosition(xOffset, textY)
lbl.Render(result.pressedToggledSurface)
if err != nil {
fmt.Printf("failed to render button pressedToggledSurface, err: %v\n", err)
}
label.SetPosition(xOffset, textY)
label.Render(v.pressedToggledSurface)
}
if buttonLayout.DisabledFrame != -1 {
result.disabledSurface, _ = renderer.NewSurface(result.width, result.height, d2enum.FilterNearest)
buttonSprite.RenderSegmented(result.disabledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.DisabledFrame)
lbl.SetPosition(xOffset, textY)
lbl.Render(result.disabledSurface)
if buttonLayout.DisabledFrame != -1 {
v.disabledSurface, _ = renderer.NewSurface(v.width, v.height, d2enum.FilterNearest)
err = buttonSprite.RenderSegmented(v.disabledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.DisabledFrame)
if err != nil {
fmt.Printf("failed to render button disabledSurface, err: %v\n", err)
}
label.SetPosition(xOffset, textY)
label.Render(v.disabledSurface)
}
}
return result
}
// OnActivated defines the callback handler for the activate event
@ -185,6 +217,7 @@ func (v *Button) Activate() {
if v.onClick == nil {
return
}
v.onClick()
}
@ -192,27 +225,37 @@ func (v *Button) Activate() {
func (v *Button) Render(target d2interface.Surface) {
target.PushFilter(d2enum.FilterNearest)
target.PushTranslation(v.x, v.y)
defer target.PopN(2)
if !v.enabled {
var err error
switch {
case !v.enabled:
target.PushColor(color.RGBA{R: 128, G: 128, B: 128, A: 195})
defer target.Pop()
target.Render(v.disabledSurface)
} else if v.toggled && v.pressed {
target.Render(v.pressedToggledSurface)
} else if v.pressed {
target.Render(v.pressedSurface)
} else if v.toggled {
target.Render(v.toggledSurface)
} else {
target.Render(v.normalSurface)
err = target.Render(v.disabledSurface)
case v.toggled && v.pressed:
err = target.Render(v.pressedToggledSurface)
case v.pressed:
err = target.Render(v.pressedSurface)
case v.toggled:
err = target.Render(v.toggledSurface)
default:
err = target.Render(v.normalSurface)
}
if err != nil {
fmt.Printf("failed to render button surface, err: %v\n", err)
}
}
// Toggle negates the toggled state of the button
func (v *Button) Toggle() {
v.toggled = !v.toggled
}
// Advance advances the button state
func (v *Button) Advance(elapsed float64) {
}
@ -227,8 +270,8 @@ func (v *Button) SetEnabled(enabled bool) {
v.enabled = enabled
}
// Size returns the size of the button
func (v *Button) GetSize() (int, int) {
// GetSize returns the size of the button
func (v *Button) GetSize() (width, height int) {
return v.width, v.height
}

View File

@ -2,9 +2,10 @@ package d2gamescreen
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
@ -170,7 +171,7 @@ func (v *Game) Advance(elapsed float64) error {
func (v *Game) bindGameControls() {
for _, player := range v.gameClient.Players {
if player.Id != v.gameClient.PlayerID {
if player.ID != v.gameClient.PlayerID {
continue
}
@ -179,7 +180,7 @@ func (v *Game) bindGameControls() {
v.gameControls.Load()
if err := v.inputManager.BindHandler(v.gameControls); err != nil {
fmt.Printf(bindControlsErrStr, player.Id)
fmt.Printf(bindControlsErrStr, player.ID)
}
break

View File

@ -71,6 +71,11 @@ const (
joinGameCharacterFilter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:"
)
// BuildInfo contains information about the current build
type BuildInfo struct {
Branch, Commit string
}
// MainMenu represents the main menu
type MainMenu struct {
tcpIPBackground *d2ui.Sprite
@ -111,6 +116,8 @@ type MainMenu struct {
audioProvider d2interface.AudioProvider
scriptEngine *d2script.ScriptEngine
navigator Navigator
buildInfo BuildInfo
}
// CreateMainMenu creates an instance of MainMenu
@ -119,6 +126,7 @@ func CreateMainMenu(
renderer d2interface.Renderer,
inputManager d2interface.InputManager,
audioProvider d2interface.AudioProvider,
buildInfo BuildInfo,
) *MainMenu {
return &MainMenu{
screenMode: ScreenModeUnknown,
@ -178,13 +186,13 @@ func (v *MainMenu) loadBackgroundSprites() {
func (v *MainMenu) createLabels(loading d2screen.LoadingState) {
v.versionLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.versionLabel.Alignment = d2gui.HorizontalAlignRight
v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch)
v.versionLabel.SetText("OpenDiablo2 - " + v.buildInfo.Branch)
v.versionLabel.Color = rgbaColor(white)
v.versionLabel.SetPosition(versionLabelX, versionLabelY)
v.commitLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
v.commitLabel.Alignment = d2gui.HorizontalAlignLeft
v.commitLabel.SetText(d2common.BuildInfo.Commit)
v.commitLabel.SetText(v.buildInfo.Commit)
v.commitLabel.Color = rgbaColor(white)
v.commitLabel.SetPosition(commitLabelX, commitLabelY)

View File

@ -165,7 +165,7 @@ func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) {
} else {
met.mapEngine = d2mapengine.CreateMapEngine() // necessary for map name update
met.mapEngine.SetSeed(time.Now().UnixNano())
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex, true)
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
//met.mapEngine.RegenerateWalkPaths()
}

View File

@ -167,7 +167,7 @@ func (g *GameClient) handleAddPlayerPacket(packet d2netpacket.NetPacket) error {
newPlayer := d2mapentity.CreatePlayer(player.ID, player.Name, player.X, player.Y, 0,
player.HeroType, player.Stats, &player.Equipment)
g.Players[newPlayer.Id] = newPlayer
g.Players[newPlayer.ID] = newPlayer
g.MapEngine.AddEntity(newPlayer)
return nil
@ -199,7 +199,7 @@ func (g *GameClient) handleMovePlayerPacket(packet d2netpacket.NetPacket) error
err := player.SetAnimationMode(player.GetAnimationMode())
if err != nil {
log.Printf("GameClient: error setting animation mode for player %s: %s", player.Id, err)
log.Printf("GameClient: error setting animation mode for player %s: %s", player.ID, err)
}
})
}

View File

@ -23,9 +23,11 @@ func CreateScriptEngine() *ScriptEngine {
fmt.Printf("Script: %s\n", call.Argument(0).String())
return otto.Value{}
})
if err != nil {
fmt.Printf("could not bind the 'debugPrint' to the given function in script engine")
}
return &ScriptEngine{
vm: vm,
isEvalAllowed: false,
@ -37,7 +39,7 @@ func (s *ScriptEngine) AllowEval() {
s.isEvalAllowed = true
}
// AllowEval disallows the evaluation of JS code.
// DisallowEval disallows the evaluation of JS code.
func (s *ScriptEngine) DisallowEval() {
s.isEvalAllowed = false
}
@ -82,5 +84,6 @@ func (s *ScriptEngine) Eval(code string) (string, error) {
if err != nil {
return "", err
}
return val.String(), nil
}