From 7a49f3637fca85325ee913f240c969509eea8a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrkan=20Kaymak?= Date: Thu, 23 Jul 2020 19:56:50 +0300 Subject: [PATCH] lint fixes (#615) --- d2app/app.go | 217 +++++++++---------- d2common/bitstream.go | 2 +- d2common/build_info.go | 20 -- d2common/d2data/d2datadict/hireling.go | 4 +- d2common/d2data/d2datadict/level_warp.go | 2 +- d2common/d2data/d2datadict/levels.go | 12 +- d2common/d2data/d2datadict/missiles.go | 2 +- d2common/d2data/d2datadict/monstats.go | 10 +- d2common/d2data/d2datadict/monstats2.go | 2 +- d2common/d2data/d2datadict/object_query.go | 10 +- d2common/d2data/d2datadict/skills.go | 2 +- d2common/d2data/d2datadict/super_uniques.go | 4 +- d2common/d2data/object.go | 12 +- d2common/d2enum/region_id.go | 2 +- d2common/d2math/ranged_number.go | 7 +- d2core/d2asset/animation.go | 1 + d2core/d2asset/composite.go | 8 +- d2core/d2asset/dc6_animation.go | 22 +- d2core/d2asset/dcc_animation.go | 2 +- d2core/d2audio/ebiten/ebiten_sound_effect.go | 5 +- d2core/d2input/ebiten/ebiten_input.go | 3 +- d2core/d2map/d2mapengine/engine.go | 23 +- d2core/d2map/d2mapengine/map_tile.go | 4 +- d2core/d2map/d2mapengine/pathfind.go | 1 + d2core/d2map/d2mapentity/animated_entity.go | 15 +- d2core/d2map/d2mapentity/map_entity.go | 1 - d2core/d2map/d2mapentity/missile.go | 3 +- d2core/d2map/d2mapentity/npc.go | 2 +- d2core/d2map/d2mapentity/player.go | 126 ++++++----- d2core/d2map/d2maprenderer/camera.go | 5 +- d2core/d2map/d2maprenderer/renderer.go | 45 ++-- d2core/d2map/d2maprenderer/tile_cache.go | 24 +- d2core/d2map/d2maprenderer/viewport.go | 57 +++-- d2core/d2render/ebiten/ebiten_renderer.go | 5 +- d2core/d2render/ebiten/ebiten_surface.go | 5 +- d2core/d2screen/d2screen.go | 12 +- d2core/d2term/terminal.go | 8 +- d2core/d2ui/button.go | 217 +++++++++++-------- d2game/d2gamescreen/game.go | 7 +- d2game/d2gamescreen/main_menu.go | 12 +- d2game/d2gamescreen/map_engine_testing.go | 2 +- d2networking/d2client/game_client.go | 4 +- d2script/engine.go | 5 +- 43 files changed, 504 insertions(+), 428 deletions(-) delete mode 100644 d2common/build_info.go diff --git a/d2app/app.go b/d2app/app.go index 1a48eaa4..ea3d0a9a 100644 --- a/d2app/app.go +++ b/d2app/app.go @@ -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) } diff --git a/d2common/bitstream.go b/d2common/bitstream.go index 543780ea..148641e1 100644 --- a/d2common/bitstream.go +++ b/d2common/bitstream.go @@ -9,7 +9,7 @@ import ( var _ d2interface.BitStream = &BitStream{} // Static check to confirm struct conforms to interface const ( - maxBits = 16 + maxBits = 16 bitsPerByte = 8 ) diff --git a/d2common/build_info.go b/d2common/build_info.go deleted file mode 100644 index a5e679f9..00000000 --- a/d2common/build_info.go +++ /dev/null @@ -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, - } -} diff --git a/d2common/d2data/d2datadict/hireling.go b/d2common/d2data/d2datadict/hireling.go index 53141aa1..21a418f4 100644 --- a/d2common/d2data/d2datadict/hireling.go +++ b/d2common/d2data/d2datadict/hireling.go @@ -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"), diff --git a/d2common/d2data/d2datadict/level_warp.go b/d2common/d2data/d2datadict/level_warp.go index 3ac24b46..58996626 100644 --- a/d2common/d2data/d2datadict/level_warp.go +++ b/d2common/d2data/d2datadict/level_warp.go @@ -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"), diff --git a/d2common/d2data/d2datadict/levels.go b/d2common/d2data/d2datadict/levels.go index e332b563..fc088d27 100644 --- a/d2common/d2data/d2datadict/levels.go +++ b/d2common/d2data/d2datadict/levels.go @@ -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"), diff --git a/d2common/d2data/d2datadict/missiles.go b/d2common/d2data/d2datadict/missiles.go index a48be0d6..c7c8746a 100644 --- a/d2common/d2data/d2datadict/missiles.go +++ b/d2common/d2data/d2datadict/missiles.go @@ -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 diff --git a/d2common/d2data/d2datadict/monstats.go b/d2common/d2data/d2datadict/monstats.go index f5cfae9a..2b6dc0f0 100644 --- a/d2common/d2data/d2datadict/monstats.go +++ b/d2common/d2data/d2datadict/monstats.go @@ -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 // don’t 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"), diff --git a/d2common/d2data/d2datadict/monstats2.go b/d2common/d2data/d2datadict/monstats2.go index 0799e95b..b7e94ff4 100644 --- a/d2common/d2data/d2datadict/monstats2.go +++ b/d2common/d2data/d2datadict/monstats2.go @@ -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"), diff --git a/d2common/d2data/d2datadict/object_query.go b/d2common/d2data/d2datadict/object_query.go index df21c380..6a5fe6c8 100644 --- a/d2common/d2data/d2datadict/object_query.go +++ b/d2common/d2data/d2datadict/object_query.go @@ -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 diff --git a/d2common/d2data/d2datadict/skills.go b/d2common/d2data/d2datadict/skills.go index 10f70ac9..b9c48608 100644 --- a/d2common/d2data/d2datadict/skills.go +++ b/d2common/d2data/d2datadict/skills.go @@ -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"), diff --git a/d2common/d2data/d2datadict/super_uniques.go b/d2common/d2data/d2datadict/super_uniques.go index ace0d9e7..9b5155eb 100644 --- a/d2common/d2data/d2datadict/super_uniques.go +++ b/d2common/d2data/d2datadict/super_uniques.go @@ -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. diff --git a/d2common/d2data/object.go b/d2common/d2data/object.go index d5632bd4..4240ad8b 100644 --- a/d2common/d2data/object.go +++ b/d2common/d2data/object.go @@ -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 } diff --git a/d2common/d2enum/region_id.go b/d2common/d2enum/region_id.go index b0d3d196..64629977 100644 --- a/d2common/d2enum/region_id.go +++ b/d2common/d2enum/region_id.go @@ -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 diff --git a/d2common/d2math/ranged_number.go b/d2common/d2math/ranged_number.go index e2ddd5d4..d4765193 100644 --- a/d2common/d2math/ranged_number.go +++ b/d2common/d2math/ranged_number.go @@ -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) } - diff --git a/d2core/d2asset/animation.go b/d2core/d2asset/animation.go index 49737815..004443e3 100644 --- a/d2core/d2asset/animation.go +++ b/d2core/d2asset/animation.go @@ -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) } diff --git a/d2core/d2asset/composite.go b/d2core/d2asset/composite.go index 58b1b43f..8a623440 100644 --- a/d2core/d2asset/composite.go +++ b/d2core/d2asset/composite.go @@ -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) + } } } } diff --git a/d2core/d2asset/dc6_animation.go b/d2core/d2asset/dc6_animation.go index 1b54932a..f7fccbb8 100644 --- a/d2core/d2asset/dc6_animation.go +++ b/d2core/d2asset/dc6_animation.go @@ -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) diff --git a/d2core/d2asset/dcc_animation.go b/d2core/d2asset/dcc_animation.go index 74925282..e858f0b2 100644 --- a/d2core/d2asset/dcc_animation.go +++ b/d2core/d2asset/dcc_animation.go @@ -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) diff --git a/d2core/d2audio/ebiten/ebiten_sound_effect.go b/d2core/d2audio/ebiten/ebiten_sound_effect.go index ae9a169c..a43dec5d 100644 --- a/d2core/d2audio/ebiten/ebiten_sound_effect.go +++ b/d2core/d2audio/ebiten/ebiten_sound_effect.go @@ -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 diff --git a/d2core/d2input/ebiten/ebiten_input.go b/d2core/d2input/ebiten/ebiten_input.go index 94a040de..1d1e0516 100644 --- a/d2core/d2input/ebiten/ebiten_input.go +++ b/d2core/d2input/ebiten/ebiten_input.go @@ -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 ( diff --git a/d2core/d2map/d2mapengine/engine.go b/d2core/d2map/d2mapengine/engine.go index 1d2813af..ae1945f9 100644 --- a/d2core/d2map/d2mapengine/engine.go +++ b/d2core/d2map/d2mapengine/engine.go @@ -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) diff --git a/d2core/d2map/d2mapengine/map_tile.go b/d2core/d2map/d2mapengine/map_tile.go index 26e5aee7..dd7bb800 100644 --- a/d2core/d2map/d2mapengine/map_tile.go +++ b/d2core/d2map/d2mapengine/map_tile.go @@ -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) diff --git a/d2core/d2map/d2mapengine/pathfind.go b/d2core/d2map/d2mapengine/pathfind.go index 47fa80cf..e033a16b 100644 --- a/d2core/d2map/d2mapengine/pathfind.go +++ b/d2core/d2map/d2mapengine/pathfind.go @@ -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) diff --git a/d2core/d2map/d2mapentity/animated_entity.go b/d2core/d2map/d2mapentity/animated_entity.go index d5b31804..d987cda8 100644 --- a/d2core/d2map/d2mapentity/animated_entity.go +++ b/d2core/d2map/d2mapentity/animated_entity.go @@ -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) + } } diff --git a/d2core/d2map/d2mapentity/map_entity.go b/d2core/d2map/d2mapentity/map_entity.go index cf5a5953..2b6d61a6 100644 --- a/d2core/d2map/d2mapentity/map_entity.go +++ b/d2core/d2map/d2mapentity/map_entity.go @@ -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 diff --git a/d2core/d2map/d2mapentity/missile.go b/d2core/d2map/d2mapentity/missile.go index 199a56d1..44f997bb 100644 --- a/d2core/d2map/d2mapentity/missile.go +++ b/d2core/d2map/d2mapentity/missile.go @@ -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) diff --git a/d2core/d2map/d2mapentity/npc.go b/d2core/d2map/d2mapentity/npc.go index 7923e7e5..d8c7e745 100644 --- a/d2core/d2map/d2mapentity/npc.go +++ b/d2core/d2map/d2mapentity/npc.go @@ -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" ) diff --git a/d2core/d2map/d2mapentity/player.go b/d2core/d2map/d2mapentity/player.go index 09a14261..9e453e6a 100644 --- a/d2core/d2map/d2mapentity/player.go +++ b/d2core/d2map/d2mapentity/player.go @@ -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 diff --git a/d2core/d2map/d2maprenderer/camera.go b/d2core/d2map/d2maprenderer/camera.go index 17ed3b2f..0014eeba 100644 --- a/d2core/d2map/d2maprenderer/camera.go +++ b/d2core/d2map/d2maprenderer/camera.go @@ -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) } diff --git a/d2core/d2map/d2maprenderer/renderer.go b/d2core/d2map/d2maprenderer/renderer.go index a2b0de1d..60948e69 100644 --- a/d2core/d2map/d2maprenderer/renderer.go +++ b/d2core/d2map/d2maprenderer/renderer.go @@ -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) diff --git a/d2core/d2map/d2maprenderer/tile_cache.go b/d2core/d2map/d2maprenderer/tile_cache.go index 9b0180cd..6c65a8b1 100644 --- a/d2core/d2map/d2maprenderer/tile_cache.go +++ b/d2core/d2map/d2maprenderer/tile_cache.go @@ -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) diff --git a/d2core/d2map/d2maprenderer/viewport.go b/d2core/d2map/d2maprenderer/viewport.go index f72a121b..080a02ba 100644 --- a/d2core/d2map/d2maprenderer/viewport.go +++ b/d2core/d2map/d2maprenderer/viewport.go @@ -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() diff --git a/d2core/d2render/ebiten/ebiten_renderer.go b/d2core/d2render/ebiten/ebiten_renderer.go index 9355a8e7..88de8db5 100644 --- a/d2core/d2render/ebiten/ebiten_renderer.go +++ b/d2core/d2render/ebiten/ebiten_renderer.go @@ -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 ( diff --git a/d2core/d2render/ebiten/ebiten_surface.go b/d2core/d2render/ebiten/ebiten_surface.go index e2721208..38cc32b9 100644 --- a/d2core/d2render/ebiten/ebiten_surface.go +++ b/d2core/d2render/ebiten/ebiten_surface.go @@ -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 ( diff --git a/d2core/d2screen/d2screen.go b/d2core/d2screen/d2screen.go index 06f78fc5..70103c90 100644 --- a/d2core/d2screen/d2screen.go +++ b/d2core/d2screen/d2screen.go @@ -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} } diff --git a/d2core/d2term/terminal.go b/d2core/d2term/terminal.go index cc230fb6..96a81c1a 100644 --- a/d2core/d2term/terminal.go +++ b/d2core/d2term/terminal.go @@ -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) diff --git a/d2core/d2ui/button.go b/d2core/d2ui/button.go index 5eb01f18..e6544f19 100644 --- a/d2core/d2ui/button.go +++ b/d2core/d2ui/button.go @@ -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 } diff --git a/d2game/d2gamescreen/game.go b/d2game/d2gamescreen/game.go index 4a82e7cc..56d56a4b 100644 --- a/d2game/d2gamescreen/game.go +++ b/d2game/d2gamescreen/game.go @@ -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 diff --git a/d2game/d2gamescreen/main_menu.go b/d2game/d2gamescreen/main_menu.go index de1aaf25..850e2ce3 100644 --- a/d2game/d2gamescreen/main_menu.go +++ b/d2game/d2gamescreen/main_menu.go @@ -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) diff --git a/d2game/d2gamescreen/map_engine_testing.go b/d2game/d2gamescreen/map_engine_testing.go index 38af3e51..92c91add 100644 --- a/d2game/d2gamescreen/map_engine_testing.go +++ b/d2game/d2gamescreen/map_engine_testing.go @@ -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() } diff --git a/d2networking/d2client/game_client.go b/d2networking/d2client/game_client.go index 9ee41f5e..e738e2bc 100644 --- a/d2networking/d2client/game_client.go +++ b/d2networking/d2client/game_client.go @@ -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) } }) } diff --git a/d2script/engine.go b/d2script/engine.go index 18d2a41a..f4a70569 100644 --- a/d2script/engine.go +++ b/d2script/engine.go @@ -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 }