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

View File

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

View File

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

View File

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

View File

@ -3,11 +3,11 @@ package d2asset
import (
"encoding/binary"
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"image/color"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
)
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.selectedHero,
d2datadict.CharStats[v.selectedHero],
v.hardcoreCheckbox.GetCheckState(),
)
v.navigator.ToCreateGame(gameState.FilePath, d2clientconnectiontype.Local, v.connectionHost)
}

View File

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

View File

@ -39,9 +39,6 @@ type StatsPanelLabels struct {
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
type HeroStatsPanel struct {
uiManager *d2ui.UIManager
@ -162,7 +159,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err
}
w, h = s.frame.GetCurrentFrameSize()
_, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, s.originY+h)
@ -177,7 +174,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err
}
w, h = s.frame.GetCurrentFrameSize()
_, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, y+h)
if err := s.frame.Render(target); err != nil {
@ -206,7 +203,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err
}
w, h = s.frame.GetCurrentFrameSize()
_, h = s.frame.GetCurrentFrameSize()
s.frame.SetPosition(x, y+h)
@ -239,7 +236,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err
}
w, h = s.panel.GetCurrentFrameSize()
_, h = s.panel.GetCurrentFrameSize()
s.panel.SetPosition(x, y+h)
@ -254,7 +251,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
return err
}
w, h = s.panel.GetCurrentFrameSize()
_, h = s.panel.GetCurrentFrameSize()
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: 477, Text: "Resistance", Font: d2resource.Font6, AlignCenter: true},
}
for _, textElement := range staticTextLabels {
label = s.createTextLabel(textElement)
label.Render(target)
@ -368,7 +366,7 @@ func (s *HeroStatsPanel) renderStatValueNum(label *d2ui.Label, value int,
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)
return s.createTextLabel(PanelText{X: x, Y: y, Text: text, Font: d2resource.Font16, AlignCenter: true})
}

View File

@ -1,6 +1,7 @@
package d2player
import (
"fmt"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
@ -13,24 +14,25 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
// Inventory represents the inventory
type Inventory struct {
uiManager *d2ui.UIManager
frame *d2ui.Sprite
panel *d2ui.Sprite
grid *ItemGrid
hoverLabel *d2ui.Label
hoverX, hoverY int
hovering bool
originX, originY int
lastMouseX, lastMouseY int
isOpen bool
uiManager *d2ui.UIManager
frame *d2ui.Sprite
panel *d2ui.Sprite
grid *ItemGrid
hoverLabel *d2ui.Label
hoverX int
hoverY int
originX int
originY int
lastMouseX int
lastMouseY int
hovering bool
isOpen bool
}
// NewInventory creates an inventory instance and returns a pointer to it
func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inventory {
hoverLabel := ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteStatic)
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 {
return g.isOpen
}
// Toggle negates the open state of the inventory
func (g *Inventory) Toggle() {
g.isOpen = !g.isOpen
}
// Open opens the inventory
func (g *Inventory) Open() {
g.isOpen = true
}
// Close closes the inventory
func (g *Inventory) Close() {
g.isOpen = false
}
// Load loads the resources required by the inventory
func (g *Inventory) Load() {
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
g.frame, _ = g.uiManager.NewSprite(animation)
@ -71,9 +78,10 @@ func (g *Inventory) Load() {
diablo2item.NewItem("rin", "Steel", "of Shock").Identify(),
diablo2item.NewItem("jav").Identify(),
diablo2item.NewItem("buc").Identify(),
//diablo2item.NewItem("Arctic Furs", "qui"),
// diablo2item.NewItem("Arctic Furs", "qui"),
// TODO: Load the player's actual items
}
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotLeftArm, diablo2item.NewItem("wnd"))
g.grid.ChangeEquippedSlot(d2enum.EquippedSlotRightArm, diablo2item.NewItem("buc"))
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.EquippedSlotNeck, diablo2item.NewItem("amu"))
// 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 {
if !g.isOpen {
return nil
@ -194,7 +207,7 @@ func (g *Inventory) Render(target d2interface.Surface) error {
return err
}
w, h = g.panel.GetCurrentFrameSize()
_, h = g.panel.GetCurrentFrameSize()
g.panel.SetPosition(x, y+h)
@ -209,7 +222,7 @@ func (g *Inventory) Render(target d2interface.Surface) error {
return err
}
w, h = g.panel.GetCurrentFrameSize()
_, h = g.panel.GetCurrentFrameSize()
g.panel.SetPosition(x, y+h)
if err := g.panel.Render(target); err != nil {

View File

@ -2,8 +2,8 @@ package d2player
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path"
"strconv"
@ -15,6 +15,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
)
// PlayerState stores the state of the player
type PlayerState struct {
HeroName string `json:"heroName"`
HeroType d2enum.Hero `json:"heroType"`
@ -22,38 +23,46 @@ type PlayerState struct {
Act int `json:"act"`
FilePath string `json:"-"`
Equipment d2inventory.CharacterEquipment `json:"equipment"`
Stats *d2hero.HeroStatsState `json:"stats"`
Stats *d2hero.HeroStatsState `json:"stats"`
X float64 `json:"x"`
Y float64 `json:"y"`
}
// HasGameStates returns true if the player has any previously saved game
func HasGameStates() bool {
basePath, _ := getGameBaseSavePath()
files, _ := ioutil.ReadDir(basePath)
return len(files) > 0
}
// GetAllPlayerStates returns all player saves
func GetAllPlayerStates() []*PlayerState {
basePath, _ := getGameBaseSavePath()
files, _ := ioutil.ReadDir(basePath)
result := make([]*PlayerState, 0)
for _, file := range files {
fileName := file.Name()
if file.IsDir() || len(fileName) < 5 || strings.ToLower(fileName[len(fileName)-4:]) != ".od2" {
continue
}
gameState := LoadPlayerState(path.Join(basePath, file.Name()))
if gameState == nil || gameState.HeroType == d2enum.HeroNone {
// temporarily loading default class stats if the character was created before saving stats was introduced
// to be removed in the future
continue
// temporarily loading default class stats if the character was created before saving stats was introduced
// to be removed in the future
} else if gameState.Stats == nil {
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)
}
return result
}
@ -63,33 +72,41 @@ func CreateTestGameState() *PlayerState {
return result
}
func LoadPlayerState(path string) *PlayerState {
strData, err := ioutil.ReadFile(path)
// LoadPlayerState loads the player state from the file
func LoadPlayerState(filePath string) *PlayerState {
strData, err := ioutil.ReadFile(filePath)
if err != nil {
return nil
}
result := &PlayerState{
FilePath: path,
FilePath: filePath,
}
err = json.Unmarshal(strData, result)
if err != nil {
return nil
}
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{
HeroName: heroName,
HeroType: hero,
Act: 1,
Stats: d2hero.CreateHeroStatsState(hero, classStats),
Stats: d2hero.CreateHeroStatsState(hero, classStats),
Equipment: d2inventory.HeroObjects[hero],
FilePath: "",
}
result.Save()
if err := result.Save(); err != nil {
fmt.Printf("failed to save game state!, err: %v\n", err)
return nil
}
return result
}
@ -105,6 +122,7 @@ func getGameBaseSavePath() (string, error) {
func getFirstFreeFileName() string {
i := 0
basePath, _ := getGameBaseSavePath()
for {
filePath := path.Join(basePath, strconv.Itoa(i)+".od2")
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 == "" {
v.FilePath = getFirstFreeFileName()
}
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()
term, err := d2term.New(inputManager)
if err != nil {
log.Fatal(err)