1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-04 17:27:16 -05:00
OpenDiablo2/d2game/d2player/player_state.go
Maxime Lavigne (malavv) d15221c21c
d2hero is *nearly* lint free #487. (#506)
Only lint left are meaningful TODOs.

I also defaulted the level and exp parameters as if we were to handle non-default state, we would need much more information. It might be worth creating another function at that point.
2020-06-30 17:03:20 -04:00

127 lines
3.2 KiB
Go

package d2player
import (
"encoding/json"
"io/ioutil"
"log"
"os"
"path"
"strconv"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
)
type PlayerState struct {
HeroName string `json:"heroName"`
HeroType d2enum.Hero `json:"heroType"`
HeroLevel int `json:"heroLevel"`
Act int `json:"act"`
FilePath string `json:"-"`
Equipment d2inventory.CharacterEquipment `json:"equipment"`
Stats *d2hero.HeroStatsState `json:"stats"`
X float64 `json:"x"`
Y float64 `json:"y"`
}
func HasGameStates() bool {
basePath, _ := getGameBaseSavePath()
files, _ := ioutil.ReadDir(basePath)
return len(files) > 0
}
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 {
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()
}
result = append(result, gameState)
}
return result
}
// CreateTestGameState is used for the map engine previewer
func CreateTestGameState() *PlayerState {
result := &PlayerState{}
return result
}
func LoadPlayerState(path string) *PlayerState {
strData, err := ioutil.ReadFile(path)
if err != nil {
return nil
}
result := &PlayerState{
FilePath: path,
}
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 {
result := &PlayerState{
HeroName: heroName,
HeroType: hero,
Act: 1,
Stats: d2hero.CreateHeroStatsState(hero, classStats),
Equipment: d2inventory.HeroObjects[hero],
FilePath: "",
}
result.Save()
return result
}
func getGameBaseSavePath() (string, error) {
configDir, err := os.UserConfigDir()
if err != nil {
return "", err
}
return path.Join(configDir, "OpenDiablo2/Saves"), nil
}
func getFirstFreeFileName() string {
i := 0
basePath, _ := getGameBaseSavePath()
for {
filePath := path.Join(basePath, strconv.Itoa(i)+".od2")
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return filePath
}
i++
}
}
func (v *PlayerState) Save() {
if v.FilePath == "" {
v.FilePath = getFirstFreeFileName()
}
if err := os.MkdirAll(path.Dir(v.FilePath), 0755); err != nil {
log.Panic(err.Error())
}
fileJson, _ := json.MarshalIndent(v, "", " ")
ioutil.WriteFile(v.FilePath, fileJson, 0644)
}