1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-16 04:25:23 +00:00

lint fixes (#703)

This commit is contained in:
Gürkan Kaymak 2020-08-12 01:01:33 +03:00 committed by GitHub
parent 2254e4b2a6
commit 858fa18068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 193 additions and 130 deletions

View File

@ -1,10 +1,10 @@
package d2dcc package d2dcc
import ( import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"log" "log"
"github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
) )
const cellsPerRow = 4 const cellsPerRow = 4
@ -35,21 +35,22 @@ type DCCDirection struct {
} }
// CreateDCCDirection creates an instance of a DCCDirection. // CreateDCCDirection creates an instance of a DCCDirection.
func CreateDCCDirection(bm *d2common.BitMuncher, func CreateDCCDirection(bm *d2common.BitMuncher, file *DCC) *DCCDirection {
file *DCC) *DCCDirection { //nolint:funlen // Can't reduce
var crazyBitTable = []byte{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32} var crazyBitTable = []byte{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
result := &DCCDirection{} result := &DCCDirection{
result.OutSizeCoded = int(bm.GetUInt32()) OutSizeCoded: int(bm.GetUInt32()),
result.CompressionFlags = int(bm.GetBits(2)) //nolint:gomnd // binary data CompressionFlags: int(bm.GetBits(2)), //nolint:gomnd // binary data
result.Variable0Bits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data Variable0Bits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.WidthBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data WidthBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.HeightBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data HeightBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.XOffsetBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data XOffsetBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.YOffsetBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data YOffsetBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.OptionalDataBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data OptionalDataBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.CodedBytesBits = int(crazyBitTable[bm.GetBits(4)]) //nolint:gomnd // binary data CodedBytesBits: int(crazyBitTable[bm.GetBits(4)]), //nolint:gomnd // binary data
result.Frames = make([]*DCCDirectionFrame, file.FramesPerDirection) Frames: make([]*DCCDirectionFrame, file.FramesPerDirection),
}
minx := 100000 minx := 100000
miny := 100000 miny := 100000
maxx := -100000 maxx := -100000
@ -81,10 +82,7 @@ func CreateDCCDirection(bm *d2common.BitMuncher,
result.RawPixelCodesBitstreamSize = int(bm.GetBits(20)) //nolint:gomnd // binary data result.RawPixelCodesBitstreamSize = int(bm.GetBits(20)) //nolint:gomnd // binary data
} }
// PixelValuesKey for paletteEntryCount, i := 0, 0; i < 256; i++ {
paletteEntryCount := 0
for i := 0; i < 256; i++ {
valid := bm.GetBit() != 0 valid := bm.GetBit() != 0
if valid { if valid {
result.PaletteEntries[paletteEntryCount] = byte(i) result.PaletteEntries[paletteEntryCount] = byte(i)
@ -132,27 +130,31 @@ func CreateDCCDirection(bm *d2common.BitMuncher,
result.PixelBuffer = nil result.PixelBuffer = nil
// Verify that everything we expected to read was actually read (sanity check)... // Verify that everything we expected to read was actually read (sanity check)...
if equalCellsBitstream.BitsRead() != result.EqualCellsBitstreamSize { result.verify(equalCellsBitstream, pixelMaskBitstream, encodingTypeBitsream, rawPixelCodesBitstream)
log.Panic("Did not read the correct number of bits!")
}
if pixelMaskBitstream.BitsRead() != result.PixelMaskBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
if encodingTypeBitsream.BitsRead() != result.EncodingTypeBitsreamSize {
log.Panic("Did not read the correct number of bits!")
}
if rawPixelCodesBitstream.BitsRead() != result.RawPixelCodesBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
bm.SkipBits(pixelCodeandDisplacement.BitsRead()) bm.SkipBits(pixelCodeandDisplacement.BitsRead())
return result return result
} }
func (v *DCCDirection) verify(equalCellsBitstream, pixelMaskBitstream, encodingTypeBitsream, rawPixelCodesBitstream *d2common.BitMuncher) {
if equalCellsBitstream.BitsRead() != v.EqualCellsBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
if pixelMaskBitstream.BitsRead() != v.PixelMaskBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
if encodingTypeBitsream.BitsRead() != v.EncodingTypeBitsreamSize {
log.Panic("Did not read the correct number of bits!")
}
if rawPixelCodesBitstream.BitsRead() != v.RawPixelCodesBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
}
//nolint:gocognit nolint:gocyclo // Can't reduce //nolint:gocognit nolint:gocyclo // Can't reduce
func (v *DCCDirection) generateFrames(pcd *d2common.BitMuncher) { func (v *DCCDirection) generateFrames(pcd *d2common.BitMuncher) {
pbIdx := 0 pbIdx := 0

View File

@ -2,12 +2,12 @@ package d2asset
import ( import (
"errors" "errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"image" "image"
"image/color" "image/color"
"math" "math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -114,9 +114,9 @@ func (a *animation) Advance(elapsed float64) error {
} }
func (a *animation) renderShadow(target d2iface.Surface) error { func (a *animation) renderShadow(target d2iface.Surface) error {
//_, height := a.GetFrameBounds()
direction := a.directions[a.directionIndex] direction := a.directions[a.directionIndex]
frame := direction.frames[a.frameIndex] frame := direction.frames[a.frameIndex]
target.PushFilter(d2enum.FilterLinear) target.PushFilter(d2enum.FilterLinear)
target.PushTranslation( target.PushTranslation(
frame.offsetX, frame.offsetX,
@ -161,8 +161,10 @@ func (a *animation) RenderFromOrigin(target d2iface.Surface, shadow bool) error
if shadow { if shadow {
_, height := a.GetFrameBounds() _, height := a.GetFrameBounds()
height = int(math.Abs(float64(height))) height = int(math.Abs(float64(height)))
target.PushTranslation((-height / 2), 0)
target.PushTranslation(-height/2, 0)
defer target.Pop() defer target.Pop()
return a.renderShadow(target) return a.renderShadow(target)
} }

View File

@ -306,6 +306,7 @@ func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weap
return nil, errors.New("animation not found") return nil, errors.New("animation not found")
} }
// GetSize returns the size of the composite
func (c *Composite) GetSize() (w, h int) { func (c *Composite) GetSize() (w, h int) {
c.updateSize() c.updateSize()
return c.size.Width, c.size.Height return c.size.Width, c.size.Height

View File

@ -2,10 +2,10 @@ package d2asset
import ( import (
"errors" "errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"math" "math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"

View File

@ -3,11 +3,11 @@ package d2asset
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"image/color" "image/color"
"strings" "strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
) )
var _ d2interface.Font = &Font{} // Static check to confirm struct conforms to interface var _ d2interface.Font = &Font{} // Static check to confirm struct conforms to interface

View File

@ -469,7 +469,6 @@ func (v *SelectHeroClass) onOkButtonClicked() {
v.heroNameTextbox.GetText(), v.heroNameTextbox.GetText(),
v.selectedHero, v.selectedHero,
d2datadict.CharStats[v.selectedHero], d2datadict.CharStats[v.selectedHero],
v.hardcoreCheckbox.GetCheckState(),
) )
v.navigator.ToCreateGame(gameState.FilePath, d2clientconnectiontype.Local, v.connectionHost) v.navigator.ToCreateGame(gameState.FilePath, d2clientconnectiontype.Local, v.connectionHost)
} }

View File

@ -38,24 +38,23 @@ const (
globeHeight = 80 globeHeight = 80
globeWidth = 80 globeWidth = 80
hoverLabelOuterPad = 5 hoverLabelOuterPad = 5
mouseBtnActionsTreshhold = 0.25
) )
// GameControls represents the game's controls on the screen // GameControls represents the game's controls on the screen
type GameControls struct { type GameControls struct {
actionableRegions []ActionableRegion
renderer d2interface.Renderer // TODO: This shouldn't be a dependency renderer d2interface.Renderer // TODO: This shouldn't be a dependency
inputListener InputCallbackListener
hero *d2mapentity.Player hero *d2mapentity.Player
mapEngine *d2mapengine.MapEngine mapEngine *d2mapengine.MapEngine
mapRenderer *d2maprenderer.MapRenderer mapRenderer *d2maprenderer.MapRenderer
uiManager *d2ui.UIManager uiManager *d2ui.UIManager
inventory *Inventory inventory *Inventory
heroStatsPanel *HeroStatsPanel heroStatsPanel *HeroStatsPanel
inputListener InputCallbackListener
FreeCam bool
lastMouseX int lastMouseX int
lastMouseY int lastMouseY int
missileID int // ID of missile to create when user right clicks. missileID int
// UI
globeSprite *d2ui.Sprite globeSprite *d2ui.Sprite
hpManaStatusSprite *d2ui.Sprite hpManaStatusSprite *d2ui.Sprite
mainPanel *d2ui.Sprite mainPanel *d2ui.Sprite
@ -64,8 +63,10 @@ type GameControls struct {
zoneChangeText *d2ui.Label zoneChangeText *d2ui.Label
nameLabel *d2ui.Label nameLabel *d2ui.Label
runButton *d2ui.Button runButton *d2ui.Button
lastLeftBtnActionTime float64
lastRightBtnActionTime float64
FreeCam bool
isZoneTextShown bool isZoneTextShown bool
actionableRegions []ActionableRegion
} }
type ActionableType int type ActionableType int
@ -87,6 +88,7 @@ const (
rightSkill = ActionableType(iota) rightSkill = ActionableType(iota)
) )
// NewGameControls creates a GameControls instance and returns a pointer to it
func NewGameControls( func NewGameControls(
renderer d2interface.Renderer, renderer d2interface.Renderer,
hero *d2mapentity.Player, hero *d2mapentity.Player,
@ -97,9 +99,13 @@ func NewGameControls(
ui *d2ui.UIManager, ui *d2ui.UIManager,
) (*GameControls, error) { ) (*GameControls, error) {
missileID := initialMissileID missileID := initialMissileID
term.BindAction("setmissile", "set missile id to summon on right click", func(id int) {
err := term.BindAction("setmissile", "set missile id to summon on right click", func(id int) {
missileID = id missileID = id
}) })
if err != nil {
return nil, err
}
zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits) zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits)
zoneLabel.Alignment = d2gui.HorizontalAlignCenter zoneLabel.Alignment = d2gui.HorizontalAlignCenter
@ -157,9 +163,11 @@ func NewGameControls(
{rightSelec, d2common.Rectangle{Left: 562, Top: 563, Width: 30, Height: 30}}, {rightSelec, d2common.Rectangle{Left: 562, Top: 563, Width: 30, Height: 30}},
{rightSkill, d2common.Rectangle{Left: 634, Top: 550, Width: 50, Height: 50}}, {rightSkill, d2common.Rectangle{Left: 634, Top: 550, Width: 50, Height: 50}},
}, },
lastLeftBtnActionTime: 0,
lastRightBtnActionTime: 0,
} }
err := term.BindAction("freecam", "toggle free camera movement", func() { err = term.BindAction("freecam", "toggle free camera movement", func() {
gc.FreeCam = !gc.FreeCam gc.FreeCam = !gc.FreeCam
}) })
@ -170,6 +178,7 @@ func NewGameControls(
return gc, nil return gc, nil
} }
// OnKeyRepeat is called to handle repeated key presses
func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool { func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool {
if g.FreeCam { if g.FreeCam {
var moveSpeed float64 = 8 var moveSpeed float64 = 8
@ -209,6 +218,7 @@ func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool {
return false return false
} }
// OnKeyDown handles key presses
func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool { func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
switch event.Key() { switch event.Key() {
case d2enum.KeyEscape: case d2enum.KeyEscape:
@ -216,6 +226,7 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
g.inventory.Close() g.inventory.Close()
g.heroStatsPanel.Close() g.heroStatsPanel.Close()
g.updateLayout() g.updateLayout()
break break
} }
case d2enum.KeyI: case d2enum.KeyI:
@ -229,13 +240,11 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
default: default:
return false return false
} }
return false return false
} }
var lastLeftBtnActionTime float64 = 0 // OnMouseButtonRepeat handles repeated mouse clicks
var lastRightBtnActionTime float64 = 0
var mouseBtnActionsTreshhold = 0.25
func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool { func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
px, py := g.mapRenderer.ScreenToWorld(event.X(), event.Y()) px, py := g.mapRenderer.ScreenToWorld(event.X(), event.Y())
px = float64(int(px*10)) / 10.0 px = float64(int(px*10)) / 10.0
@ -245,14 +254,14 @@ func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
button := event.Button() button := event.Button()
isLeft := button == d2enum.MouseButtonLeft isLeft := button == d2enum.MouseButtonLeft
isRight := button == d2enum.MouseButtonRight isRight := button == d2enum.MouseButtonRight
lastLeft := now - lastLeftBtnActionTime lastLeft := now - g.lastLeftBtnActionTime
lastRight := now - lastRightBtnActionTime lastRight := now - g.lastRightBtnActionTime
inRect := !g.isInActiveMenusRect(event.X(), event.Y()) inRect := !g.isInActiveMenusRect(event.X(), event.Y())
shouldDoLeft := lastLeft >= mouseBtnActionsTreshhold shouldDoLeft := lastLeft >= mouseBtnActionsTreshhold
shouldDoRight := lastRight >= mouseBtnActionsTreshhold shouldDoRight := lastRight >= mouseBtnActionsTreshhold
if isLeft && shouldDoLeft && inRect { if isLeft && shouldDoLeft && inRect {
lastLeftBtnActionTime = now g.lastLeftBtnActionTime = now
g.inputListener.OnPlayerMove(px, py) g.inputListener.OnPlayerMove(px, py)
@ -274,7 +283,7 @@ func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
} }
if isRight && shouldDoRight && inRect { if isRight && shouldDoRight && inRect {
lastRightBtnActionTime = now g.lastRightBtnActionTime = now
g.inputListener.OnPlayerCast(g.missileID, px, py) g.inputListener.OnPlayerCast(g.missileID, px, py)
@ -284,6 +293,7 @@ func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
return true return true
} }
// OnMouseMove handles mouse movement events
func (g *GameControls) OnMouseMove(event d2interface.MouseMoveEvent) bool { func (g *GameControls) OnMouseMove(event d2interface.MouseMoveEvent) bool {
mx, my := event.X(), event.Y() mx, my := event.X(), event.Y()
g.lastMouseX = mx g.lastMouseX = mx
@ -301,6 +311,7 @@ func (g *GameControls) OnMouseMove(event d2interface.MouseMoveEvent) bool {
return false return false
} }
// OnMouseButtonDown handles mouse button presses
func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool { func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
mx, my := event.X(), event.Y() mx, my := event.X(), event.Y()
@ -317,7 +328,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
py = float64(int(py*10)) / 10.0 py = float64(int(py*10)) / 10.0
if event.Button() == d2enum.MouseButtonLeft && !g.isInActiveMenusRect(mx, my) { if event.Button() == d2enum.MouseButtonLeft && !g.isInActiveMenusRect(mx, my) {
lastLeftBtnActionTime = d2common.Now() g.lastLeftBtnActionTime = d2common.Now()
g.inputListener.OnPlayerMove(px, py) g.inputListener.OnPlayerMove(px, py)
@ -325,7 +336,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
} }
if event.Button() == d2enum.MouseButtonRight && !g.isInActiveMenusRect(mx, my) { if event.Button() == d2enum.MouseButtonRight && !g.isInActiveMenusRect(mx, my) {
lastRightBtnActionTime = d2common.Now() g.lastRightBtnActionTime = d2common.Now()
g.inputListener.OnPlayerCast(g.missileID, px, py) g.inputListener.OnPlayerCast(g.missileID, px, py)
@ -335,6 +346,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
return false return false
} }
// Load loads the resources required for the GameControls
func (g *GameControls) Load() { func (g *GameControls) Load() {
animation, _ := d2asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
g.globeSprite, _ = g.uiManager.NewSprite(animation) g.globeSprite, _ = g.uiManager.NewSprite(animation)
@ -376,6 +388,7 @@ func (g *GameControls) onToggleRunButton() {
g.hero.SetIsRunning(g.hero.IsRunToggled()) g.hero.SetIsRunning(g.hero.IsRunToggled())
} }
// Advance advances the state of the GameControls
func (g *GameControls) Advance(elapsed float64) error { func (g *GameControls) Advance(elapsed float64) error {
g.mapRenderer.Advance(elapsed) g.mapRenderer.Advance(elapsed)
return nil return nil
@ -385,11 +398,12 @@ func (g *GameControls) updateLayout() {
isRightPanelOpen := g.isLeftPanelOpen() isRightPanelOpen := g.isLeftPanelOpen()
isLeftPanelOpen := g.isRightPanelOpen() isLeftPanelOpen := g.isRightPanelOpen()
if isRightPanelOpen == isLeftPanelOpen { switch {
case isRightPanelOpen == isLeftPanelOpen:
g.mapRenderer.ViewportDefault() g.mapRenderer.ViewportDefault()
} else if isRightPanelOpen { case isRightPanelOpen:
g.mapRenderer.ViewportToLeft() g.mapRenderer.ViewportToLeft()
} else { default:
g.mapRenderer.ViewportToRight() g.mapRenderer.ViewportToRight()
} }
} }
@ -404,7 +418,7 @@ func (g *GameControls) isRightPanelOpen() bool {
return g.inventory.IsOpen() return g.inventory.IsOpen()
} }
func (g *GameControls) isInActiveMenusRect(px int, py int) bool { func (g *GameControls) isInActiveMenusRect(px, py int) bool {
var bottomMenuRect = d2common.Rectangle{Left: 0, Top: 550, Width: 800, Height: 50} var bottomMenuRect = d2common.Rectangle{Left: 0, Top: 550, Width: 800, Height: 50}
var leftMenuRect = d2common.Rectangle{Left: 0, Top: 0, Width: 400, Height: 600} var leftMenuRect = d2common.Rectangle{Left: 0, Top: 0, Width: 400, Height: 600}
@ -427,6 +441,7 @@ func (g *GameControls) isInActiveMenusRect(px int, py int) bool {
} }
// TODO: consider caching the panels to single image that is reused. // TODO: consider caching the panels to single image that is reused.
// Render draws the GameControls onto the target
func (g *GameControls) Render(target d2interface.Surface) error { func (g *GameControls) Render(target d2interface.Surface) error {
for entityIdx := range g.mapEngine.Entities() { for entityIdx := range g.mapEngine.Entities() {
entity := (g.mapEngine.Entities())[entityIdx] entity := (g.mapEngine.Entities())[entityIdx]
@ -463,8 +478,13 @@ func (g *GameControls) Render(target d2interface.Surface) error {
} }
} }
g.heroStatsPanel.Render(target) if err := g.heroStatsPanel.Render(target); err != nil {
g.inventory.Render(target) return err
}
if err := g.inventory.Render(target); err != nil {
return err
}
width, height := target.GetSize() width, height := target.GetSize()
offset := 0 offset := 0
@ -679,14 +699,17 @@ func (g *GameControls) Render(target d2interface.Surface) error {
return nil return nil
} }
// SetZoneChangeText sets the zoneChangeText
func (g *GameControls) SetZoneChangeText(text string) { func (g *GameControls) SetZoneChangeText(text string) {
g.zoneChangeText.SetText(text) g.zoneChangeText.SetText(text)
} }
// ShowZoneChangeText shows the zoneChangeText
func (g *GameControls) ShowZoneChangeText() { func (g *GameControls) ShowZoneChangeText() {
g.isZoneTextShown = true g.isZoneTextShown = true
} }
// HideZoneChangeTextAfter hides the zoneChangeText after the given amount of seconds
func (g *GameControls) HideZoneChangeTextAfter(delay float64) { func (g *GameControls) HideZoneChangeTextAfter(delay float64) {
time.AfterFunc(time.Duration(delay)*time.Second, func() { time.AfterFunc(time.Duration(delay)*time.Second, func() {
g.isZoneTextShown = false g.isZoneTextShown = false

View File

@ -39,9 +39,6 @@ type StatsPanelLabels struct {
Stamina *d2ui.Label Stamina *d2ui.Label
} }
// stores all the labels that can change during gameplay(e.g. current level, current hp, mana, etc.)
var StatValueLabels = make([]d2ui.Label, 13)
// HeroStatsPanel represents the hero status panel // HeroStatsPanel represents the hero status panel
type HeroStatsPanel struct { type HeroStatsPanel struct {
uiManager *d2ui.UIManager uiManager *d2ui.UIManager
@ -162,7 +159,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err return err
} }
w, h = s.frame.GetCurrentFrameSize() _, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, s.originY+h) s.frame.SetPosition(x, s.originY+h)
@ -177,7 +174,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err return err
} }
w, h = s.frame.GetCurrentFrameSize() _, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, y+h) s.frame.SetPosition(x, y+h)
if err := s.frame.Render(target); err != nil { if err := s.frame.Render(target); err != nil {
@ -206,7 +203,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err return err
} }
w, h = s.frame.GetCurrentFrameSize() _, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, y+h) s.frame.SetPosition(x, y+h)
@ -239,7 +236,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err return err
} }
w, h = s.panel.GetCurrentFrameSize() _, h = s.panel.GetCurrentFrameSize()
s.panel.SetPosition(x, y+h) s.panel.SetPosition(x, y+h)
@ -254,7 +251,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err return err
} }
w, h = s.panel.GetCurrentFrameSize() _, h = s.panel.GetCurrentFrameSize()
s.panel.SetPosition(x, y+h) s.panel.SetPosition(x, y+h)
@ -306,6 +303,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
{X: 310, Y: 468, Text: "Poison", Font: d2resource.Font6, AlignCenter: true}, {X: 310, Y: 468, Text: "Poison", Font: d2resource.Font6, AlignCenter: true},
{X: 310, Y: 477, Text: "Resistance", Font: d2resource.Font6, AlignCenter: true}, {X: 310, Y: 477, Text: "Resistance", Font: d2resource.Font6, AlignCenter: true},
} }
for _, textElement := range staticTextLabels { for _, textElement := range staticTextLabels {
label = s.createTextLabel(textElement) label = s.createTextLabel(textElement)
label.Render(target) label.Render(target)
@ -368,7 +366,7 @@ func (s *HeroStatsPanel) renderStatValueNum(label *d2ui.Label, value int,
label.Render(target) label.Render(target)
} }
func (s *HeroStatsPanel) createStatValueLabel(stat int, x int, y int) *d2ui.Label { func (s *HeroStatsPanel) createStatValueLabel(stat, x, y int) *d2ui.Label {
text := strconv.Itoa(stat) text := strconv.Itoa(stat)
return s.createTextLabel(PanelText{X: x, Y: y, Text: text, Font: d2resource.Font16, AlignCenter: true}) return s.createTextLabel(PanelText{X: x, Y: y, Text: text, Font: d2resource.Font16, AlignCenter: true})
} }

View File

@ -1,6 +1,7 @@
package d2player package d2player
import ( import (
"fmt"
"image/color" "image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
@ -13,24 +14,25 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
// Inventory represents the inventory
type Inventory struct { type Inventory struct {
uiManager *d2ui.UIManager uiManager *d2ui.UIManager
frame *d2ui.Sprite frame *d2ui.Sprite
panel *d2ui.Sprite panel *d2ui.Sprite
grid *ItemGrid grid *ItemGrid
hoverLabel *d2ui.Label hoverLabel *d2ui.Label
hoverX, hoverY int hoverX int
hoverY int
originX int
originY int
lastMouseX int
lastMouseY int
hovering bool hovering bool
originX, originY int
lastMouseX, lastMouseY int
isOpen bool isOpen bool
} }
// NewInventory creates an inventory instance and returns a pointer to it
func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inventory { func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inventory {
hoverLabel := ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteStatic) hoverLabel := ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteStatic)
hoverLabel.Alignment = d2gui.HorizontalAlignCenter hoverLabel.Alignment = d2gui.HorizontalAlignCenter
@ -44,22 +46,27 @@ func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inven
} }
} }
// IsOpen returns true if the inventory is open
func (g *Inventory) IsOpen() bool { func (g *Inventory) IsOpen() bool {
return g.isOpen return g.isOpen
} }
// Toggle negates the open state of the inventory
func (g *Inventory) Toggle() { func (g *Inventory) Toggle() {
g.isOpen = !g.isOpen g.isOpen = !g.isOpen
} }
// Open opens the inventory
func (g *Inventory) Open() { func (g *Inventory) Open() {
g.isOpen = true g.isOpen = true
} }
// Close closes the inventory
func (g *Inventory) Close() { func (g *Inventory) Close() {
g.isOpen = false g.isOpen = false
} }
// Load loads the resources required by the inventory
func (g *Inventory) Load() { func (g *Inventory) Load() {
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
g.frame, _ = g.uiManager.NewSprite(animation) g.frame, _ = g.uiManager.NewSprite(animation)
@ -74,6 +81,7 @@ func (g *Inventory) Load() {
// diablo2item.NewItem("Arctic Furs", "qui"), // diablo2item.NewItem("Arctic Furs", "qui"),
// TODO: Load the player's actual items // TODO: Load the player's actual items
} }
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotLeftArm, diablo2item.NewItem("wnd")) g.grid.ChangeEquippedSlot(d2enum.EquippedSlotLeftArm, diablo2item.NewItem("wnd"))
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotRightArm, diablo2item.NewItem("buc")) g.grid.ChangeEquippedSlot(d2enum.EquippedSlotRightArm, diablo2item.NewItem("buc"))
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotHead, diablo2item.NewItem("crn")) g.grid.ChangeEquippedSlot(d2enum.EquippedSlotHead, diablo2item.NewItem("crn"))
@ -85,9 +93,14 @@ func (g *Inventory) Load() {
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotRightHand, diablo2item.NewItem("rin")) g.grid.ChangeEquippedSlot(d2enum.EquippedSlotRightHand, diablo2item.NewItem("rin"))
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotNeck, diablo2item.NewItem("amu")) g.grid.ChangeEquippedSlot(d2enum.EquippedSlotNeck, diablo2item.NewItem("amu"))
// TODO: Load the player's actual items // TODO: Load the player's actual items
g.grid.Add(items...)
_, err := g.grid.Add(items...)
if err != nil {
fmt.Printf("could not add items to the inventory, err: %v\n", err)
}
} }
// Render draws the inventory onto the given surface
func (g *Inventory) Render(target d2interface.Surface) error { func (g *Inventory) Render(target d2interface.Surface) error {
if !g.isOpen { if !g.isOpen {
return nil return nil
@ -194,7 +207,7 @@ func (g *Inventory) Render(target d2interface.Surface) error {
return err return err
} }
w, h = g.panel.GetCurrentFrameSize() _, h = g.panel.GetCurrentFrameSize()
g.panel.SetPosition(x, y+h) g.panel.SetPosition(x, y+h)
@ -209,7 +222,7 @@ func (g *Inventory) Render(target d2interface.Surface) error {
return err return err
} }
w, h = g.panel.GetCurrentFrameSize() _, h = g.panel.GetCurrentFrameSize()
g.panel.SetPosition(x, y+h) g.panel.SetPosition(x, y+h)
if err := g.panel.Render(target); err != nil { if err := g.panel.Render(target); err != nil {

View File

@ -2,8 +2,8 @@ package d2player
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path" "path"
"strconv" "strconv"
@ -15,6 +15,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
) )
// PlayerState stores the state of the player
type PlayerState struct { type PlayerState struct {
HeroName string `json:"heroName"` HeroName string `json:"heroName"`
HeroType d2enum.Hero `json:"heroType"` HeroType d2enum.Hero `json:"heroType"`
@ -27,33 +28,41 @@ type PlayerState struct {
Y float64 `json:"y"` Y float64 `json:"y"`
} }
// HasGameStates returns true if the player has any previously saved game
func HasGameStates() bool { func HasGameStates() bool {
basePath, _ := getGameBaseSavePath() basePath, _ := getGameBaseSavePath()
files, _ := ioutil.ReadDir(basePath) files, _ := ioutil.ReadDir(basePath)
return len(files) > 0 return len(files) > 0
} }
// GetAllPlayerStates returns all player saves
func GetAllPlayerStates() []*PlayerState { func GetAllPlayerStates() []*PlayerState {
basePath, _ := getGameBaseSavePath() basePath, _ := getGameBaseSavePath()
files, _ := ioutil.ReadDir(basePath) files, _ := ioutil.ReadDir(basePath)
result := make([]*PlayerState, 0) result := make([]*PlayerState, 0)
for _, file := range files { for _, file := range files {
fileName := file.Name() fileName := file.Name()
if file.IsDir() || len(fileName) < 5 || strings.ToLower(fileName[len(fileName)-4:]) != ".od2" { if file.IsDir() || len(fileName) < 5 || strings.ToLower(fileName[len(fileName)-4:]) != ".od2" {
continue continue
} }
gameState := LoadPlayerState(path.Join(basePath, file.Name())) gameState := LoadPlayerState(path.Join(basePath, file.Name()))
if gameState == nil || gameState.HeroType == d2enum.HeroNone { if gameState == nil || gameState.HeroType == d2enum.HeroNone {
continue
// temporarily loading default class stats if the character was created before saving stats was introduced // temporarily loading default class stats if the character was created before saving stats was introduced
// to be removed in the future // to be removed in the future
continue
} else if gameState.Stats == nil { } else if gameState.Stats == nil {
gameState.Stats = d2hero.CreateHeroStatsState(gameState.HeroType, d2datadict.CharStats[gameState.HeroType]) gameState.Stats = d2hero.CreateHeroStatsState(gameState.HeroType, d2datadict.CharStats[gameState.HeroType])
gameState.Save() if err := gameState.Save(); err != nil {
fmt.Printf("failed to save game state!, err: %v\n", err)
}
} }
result = append(result, gameState) result = append(result, gameState)
} }
return result return result
} }
@ -63,23 +72,27 @@ func CreateTestGameState() *PlayerState {
return result return result
} }
func LoadPlayerState(path string) *PlayerState { // LoadPlayerState loads the player state from the file
strData, err := ioutil.ReadFile(path) func LoadPlayerState(filePath string) *PlayerState {
strData, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
return nil return nil
} }
result := &PlayerState{ result := &PlayerState{
FilePath: path, FilePath: filePath,
} }
err = json.Unmarshal(strData, result) err = json.Unmarshal(strData, result)
if err != nil { if err != nil {
return nil return nil
} }
return result return result
} }
func CreatePlayerState(heroName string, hero d2enum.Hero, classStats *d2datadict.CharStatsRecord, hardcore bool) *PlayerState { // CreatePlayerState creates a PlayerState instance and returns a pointer to it
func CreatePlayerState(heroName string, hero d2enum.Hero, classStats *d2datadict.CharStatsRecord) *PlayerState {
result := &PlayerState{ result := &PlayerState{
HeroName: heroName, HeroName: heroName,
HeroType: hero, HeroType: hero,
@ -89,7 +102,11 @@ func CreatePlayerState(heroName string, hero d2enum.Hero, classStats *d2datadict
FilePath: "", FilePath: "",
} }
result.Save() if err := result.Save(); err != nil {
fmt.Printf("failed to save game state!, err: %v\n", err)
return nil
}
return result return result
} }
@ -105,6 +122,7 @@ func getGameBaseSavePath() (string, error) {
func getFirstFreeFileName() string { func getFirstFreeFileName() string {
i := 0 i := 0
basePath, _ := getGameBaseSavePath() basePath, _ := getGameBaseSavePath()
for { for {
filePath := path.Join(basePath, strconv.Itoa(i)+".od2") filePath := path.Join(basePath, strconv.Itoa(i)+".od2")
if _, err := os.Stat(filePath); os.IsNotExist(err) { if _, err := os.Stat(filePath); os.IsNotExist(err) {
@ -114,13 +132,19 @@ func getFirstFreeFileName() string {
} }
} }
func (v *PlayerState) Save() { // Save saves the player state to a file
func (v *PlayerState) Save() error {
if v.FilePath == "" { if v.FilePath == "" {
v.FilePath = getFirstFreeFileName() v.FilePath = getFirstFreeFileName()
} }
if err := os.MkdirAll(path.Dir(v.FilePath), 0755); err != nil { if err := os.MkdirAll(path.Dir(v.FilePath), 0755); err != nil {
log.Panic(err.Error()) return err
} }
fileJson, _ := json.MarshalIndent(v, "", " ")
ioutil.WriteFile(v.FilePath, fileJson, 0644) fileJSON, _ := json.MarshalIndent(v, "", " ")
if err := ioutil.WriteFile(v.FilePath, fileJSON, 0644); err != nil {
return err
}
return nil
} }

View File

@ -40,6 +40,7 @@ func main() {
} }
inputManager := d2input.NewInputManager() inputManager := d2input.NewInputManager()
term, err := d2term.New(inputManager) term, err := d2term.New(inputManager)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)