mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-27 21:56:19 -04:00
remove d2asset singleton (#726)
* export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
This commit is contained in:
parent
f4a71c72e4
commit
854fce3b14
38
d2app/app.go
38
d2app/app.go
@ -60,6 +60,7 @@ type App struct {
|
|||||||
captureFrames []*image.RGBA
|
captureFrames []*image.RGBA
|
||||||
gitBranch string
|
gitBranch string
|
||||||
gitCommit string
|
gitCommit string
|
||||||
|
asset *d2asset.AssetManager
|
||||||
inputManager d2interface.InputManager
|
inputManager d2interface.InputManager
|
||||||
terminal d2interface.Terminal
|
terminal d2interface.Terminal
|
||||||
scriptEngine *d2script.ScriptEngine
|
scriptEngine *d2script.ScriptEngine
|
||||||
@ -89,8 +90,9 @@ func Create(gitBranch, gitCommit string,
|
|||||||
scriptEngine *d2script.ScriptEngine,
|
scriptEngine *d2script.ScriptEngine,
|
||||||
audio d2interface.AudioProvider,
|
audio d2interface.AudioProvider,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
) *App {
|
) *App {
|
||||||
uiManager := d2ui.NewUIManager(renderer, inputManager, audio)
|
uiManager := d2ui.NewUIManager(asset, renderer, inputManager, audio)
|
||||||
screenManager := d2screen.NewScreenManager(uiManager)
|
screenManager := d2screen.NewScreenManager(uiManager)
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
@ -103,6 +105,7 @@ func Create(gitBranch, gitCommit string,
|
|||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
ui: uiManager,
|
ui: uiManager,
|
||||||
screen: screenManager,
|
screen: screenManager,
|
||||||
|
asset: asset,
|
||||||
tAllocSamples: createZeroedRing(nSamplesTAlloc),
|
tAllocSamples: createZeroedRing(nSamplesTAlloc),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,11 +177,7 @@ func (a *App) initialize() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d2asset.Initialize(a.renderer, a.terminal); err != nil {
|
if err := d2gui.Initialize(a.asset, a.inputManager); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := d2gui.Initialize(a.inputManager); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +207,7 @@ func (a *App) loadStrings() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tablePath := range tablePaths {
|
for _, tablePath := range tablePaths {
|
||||||
data, err := d2asset.LoadFile(tablePath)
|
data, err := a.asset.LoadFile(tablePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -298,7 +297,7 @@ func (a *App) loadDataDict() error {
|
|||||||
d2datadict.InitObjectRecords()
|
d2datadict.InitObjectRecords()
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
data, err := d2asset.LoadFile(entry.path)
|
data, err := a.asset.LoadFile(entry.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -678,42 +677,51 @@ func updateInitError(target d2interface.Surface) error {
|
|||||||
// ToMainMenu forces the game to transition to the Main Menu
|
// ToMainMenu forces the game to transition to the Main Menu
|
||||||
func (a *App) ToMainMenu() {
|
func (a *App) ToMainMenu() {
|
||||||
buildInfo := d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit}
|
buildInfo := d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit}
|
||||||
mainMenu := d2gamescreen.CreateMainMenu(a, a.renderer, a.inputManager, a.audio, a.ui, buildInfo)
|
|
||||||
|
mainMenu := d2gamescreen.CreateMainMenu(a, a.asset, a.renderer, a.inputManager, a.audio, a.ui,
|
||||||
|
buildInfo)
|
||||||
|
|
||||||
a.screen.SetNextScreen(mainMenu)
|
a.screen.SetNextScreen(mainMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSelectHero forces the game to transition to the Select Hero (create character) screen
|
// ToSelectHero forces the game to transition to the Select Hero (create character) screen
|
||||||
func (a *App) ToSelectHero(connType d2clientconnectiontype.ClientConnectionType, host string) {
|
func (a *App) ToSelectHero(connType d2clientconnectiontype.ClientConnectionType, host string) {
|
||||||
selectHero := d2gamescreen.CreateSelectHeroClass(a, a.renderer, a.audio, a.ui, connType, host)
|
selectHero := d2gamescreen.CreateSelectHeroClass(a, a.asset, a.renderer, a.audio, a.ui,
|
||||||
|
connType, host)
|
||||||
a.screen.SetNextScreen(selectHero)
|
a.screen.SetNextScreen(selectHero)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToCreateGame forces the game to transition to the Create Game screen
|
// ToCreateGame forces the game to transition to the Create Game screen
|
||||||
func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.ClientConnectionType, host string) {
|
func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.ClientConnectionType, host string) {
|
||||||
gameClient, _ := d2client.Create(connType, a.scriptEngine)
|
gameClient, _ := d2client.Create(connType, a.asset, a.scriptEngine)
|
||||||
|
|
||||||
if err := gameClient.Open(host, filePath); err != nil {
|
if err := gameClient.Open(host, filePath); err != nil {
|
||||||
// TODO an error screen should be shown in this case
|
// TODO an error screen should be shown in this case
|
||||||
fmt.Printf("can not connect to the host: %s", host)
|
fmt.Printf("can not connect to the host: %s", host)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.screen.SetNextScreen(d2gamescreen.CreateGame(a, a.renderer, a.inputManager, a.audio, gameClient, a.terminal))
|
a.screen.SetNextScreen(d2gamescreen.CreateGame(a, a.asset, a.ui, a.renderer, a.inputManager,
|
||||||
|
a.audio, gameClient, a.terminal))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToCharacterSelect forces the game to transition to the Character Select (load character) screen
|
// ToCharacterSelect forces the game to transition to the Character Select (load character) screen
|
||||||
func (a *App) ToCharacterSelect(connType d2clientconnectiontype.ClientConnectionType, connHost string) {
|
func (a *App) ToCharacterSelect(connType d2clientconnectiontype.ClientConnectionType, connHost string) {
|
||||||
characterSelect := d2gamescreen.CreateCharacterSelect(a, a.renderer, a.inputManager, a.audio, a.ui, connType, connHost)
|
|
||||||
|
characterSelect := d2gamescreen.CreateCharacterSelect(a, a.asset, a.renderer, a.inputManager,
|
||||||
|
a.audio, a.ui, connType, connHost)
|
||||||
|
|
||||||
a.screen.SetNextScreen(characterSelect)
|
a.screen.SetNextScreen(characterSelect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMapEngineTest forces the game to transition to the map engine test screen
|
// ToMapEngineTest forces the game to transition to the map engine test screen
|
||||||
func (a *App) ToMapEngineTest(region, level int) {
|
func (a *App) ToMapEngineTest(region, level int) {
|
||||||
met := d2gamescreen.CreateMapEngineTest(region, level, a.terminal, a.renderer, a.inputManager,
|
met := d2gamescreen.CreateMapEngineTest(region, level, a.asset, a.terminal, a.renderer,
|
||||||
|
a.inputManager,
|
||||||
a.audio, a.screen)
|
a.audio, a.screen)
|
||||||
a.screen.SetNextScreen(met)
|
a.screen.SetNextScreen(met)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToCredits forces the game to transition to the credits screen
|
// ToCredits forces the game to transition to the credits screen
|
||||||
func (a *App) ToCredits() {
|
func (a *App) ToCredits() {
|
||||||
a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.renderer, a.ui))
|
a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.asset, a.renderer, a.ui))
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ var _ d2interface.AnimationManager = &animationManager{}
|
|||||||
var _ d2interface.Cacher = &animationManager{}
|
var _ d2interface.Cacher = &animationManager{}
|
||||||
|
|
||||||
type animationManager struct {
|
type animationManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
}
|
}
|
||||||
@ -31,13 +33,6 @@ func (am *animationManager) GetCache() d2interface.Cache {
|
|||||||
return am.cache
|
return am.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAnimationManager(renderer d2interface.Renderer) *animationManager {
|
|
||||||
return &animationManager{
|
|
||||||
renderer: renderer,
|
|
||||||
cache: d2cache.CreateCache(animationBudget),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *animationManager) LoadAnimation(
|
func (am *animationManager) LoadAnimation(
|
||||||
animationPath, palettePath string,
|
animationPath, palettePath string,
|
||||||
effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||||
@ -51,22 +46,22 @@ func (am *animationManager) LoadAnimation(
|
|||||||
ext := strings.ToLower(filepath.Ext(animationPath))
|
ext := strings.ToLower(filepath.Ext(animationPath))
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".dc6":
|
case ".dc6":
|
||||||
palette, err := LoadPalette(palettePath)
|
palette, err := am.LoadPalette(palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
animation, err = CreateDC6Animation(am.renderer, animationPath, palette, d2enum.DrawEffectNone)
|
animation, err = am.CreateDC6Animation(animationPath, palette, d2enum.DrawEffectNone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case ".dcc":
|
case ".dcc":
|
||||||
palette, err := LoadPalette(palettePath)
|
palette, err := am.LoadPalette(palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
animation, err = CreateDCCAnimation(am.renderer, animationPath, palette, effect)
|
animation, err = am.CreateDCCAnimation(animationPath, palette, effect)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -80,3 +75,85 @@ func (am *animationManager) LoadAnimation(
|
|||||||
|
|
||||||
return animation, nil
|
return animation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
||||||
|
func (am *animationManager) CreateDC6Animation(dc6Path string,
|
||||||
|
palette d2interface.Palette, effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||||
|
dc6, err := am.loadDC6(dc6Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
anim := DC6Animation{
|
||||||
|
animation: animation{
|
||||||
|
directions: make([]animationDirection, dc6.Directions),
|
||||||
|
playLength: defaultPlayLength,
|
||||||
|
playLoop: true,
|
||||||
|
originAtBottom: true,
|
||||||
|
effect: effect,
|
||||||
|
},
|
||||||
|
dc6Path: dc6Path,
|
||||||
|
dc6: dc6,
|
||||||
|
palette: palette,
|
||||||
|
renderer: am.renderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = anim.SetDirection(0)
|
||||||
|
|
||||||
|
return &anim, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDCCAnimation creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||||
|
func (am *animationManager) CreateDCCAnimation(dccPath string,
|
||||||
|
palette d2interface.Palette,
|
||||||
|
effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||||
|
dcc, err := am.loadDCC(dccPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
anim := animation{
|
||||||
|
playLength: defaultPlayLength,
|
||||||
|
playLoop: true,
|
||||||
|
directions: make([]animationDirection, dcc.NumberOfDirections),
|
||||||
|
effect: effect,
|
||||||
|
}
|
||||||
|
|
||||||
|
DCC := DCCAnimation{
|
||||||
|
animation: anim,
|
||||||
|
animationManager: am,
|
||||||
|
dccPath: dccPath,
|
||||||
|
palette: palette,
|
||||||
|
renderer: am.renderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = DCC.SetDirection(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DCC, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *animationManager) loadDC6(path string) (*d2dc6.DC6, error) {
|
||||||
|
dc6Data, err := am.LoadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dc6, err := d2dc6.Load(dc6Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dc6, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *animationManager) loadDCC(path string) (*d2dcc.DCC, error) {
|
||||||
|
dccData, err := am.LoadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d2dcc.Load(dccData)
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
@ -16,6 +15,7 @@ var _ d2interface.ArchiveManager = &archiveManager{}
|
|||||||
var _ d2interface.Cacher = &archiveManager{}
|
var _ d2interface.Cacher = &archiveManager{}
|
||||||
|
|
||||||
type archiveManager struct {
|
type archiveManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
config *d2config.Configuration
|
config *d2config.Configuration
|
||||||
archives []d2interface.Archive
|
archives []d2interface.Archive
|
||||||
@ -26,10 +26,6 @@ const (
|
|||||||
archiveBudget = 1024 * 1024 * 512
|
archiveBudget = 1024 * 1024 * 512
|
||||||
)
|
)
|
||||||
|
|
||||||
func createArchiveManager(config *d2config.Configuration) d2interface.ArchiveManager {
|
|
||||||
return &archiveManager{cache: d2cache.CreateCache(archiveBudget), config: config}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadArchiveForFile loads the archive for the given (in-archive) file path
|
// LoadArchiveForFile loads the archive for the given (in-archive) file path
|
||||||
func (am *archiveManager) LoadArchiveForFile(filePath string) (d2interface.Archive, error) {
|
func (am *archiveManager) LoadArchiveForFile(filePath string) (d2interface.Archive, error) {
|
||||||
am.mutex.Lock()
|
am.mutex.Lock()
|
||||||
|
@ -3,7 +3,6 @@ package d2asset
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
@ -18,20 +17,12 @@ var _ d2interface.FileManager = &fileManager{}
|
|||||||
var _ d2interface.Cacher = &fileManager{}
|
var _ d2interface.Cacher = &fileManager{}
|
||||||
|
|
||||||
type fileManager struct {
|
type fileManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
archiveManager d2interface.ArchiveManager
|
archiveManager d2interface.ArchiveManager
|
||||||
config *d2config.Configuration
|
config *d2config.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFileManager(config *d2config.Configuration,
|
|
||||||
archiveManager d2interface.ArchiveManager) d2interface.FileManager {
|
|
||||||
return &fileManager{
|
|
||||||
d2cache.CreateCache(fileBudget),
|
|
||||||
archiveManager,
|
|
||||||
config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFileStream loads a file as a stream automatically from an archive
|
// LoadFileStream loads a file as a stream automatically from an archive
|
||||||
func (fm *fileManager) LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
func (fm *fileManager) LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
||||||
filePath = fm.fixupFilePath(filePath)
|
filePath = fm.fixupFilePath(filePath)
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
"log"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
type assetManager struct {
|
// AssetManager loads files and game objects
|
||||||
|
type AssetManager struct {
|
||||||
archiveManager d2interface.ArchiveManager
|
archiveManager d2interface.ArchiveManager
|
||||||
archivedFileManager d2interface.FileManager
|
archivedFileManager d2interface.FileManager
|
||||||
paletteManager d2interface.PaletteManager
|
paletteManager d2interface.PaletteManager
|
||||||
@ -16,39 +17,66 @@ type assetManager struct {
|
|||||||
fontManager d2interface.FontManager
|
fontManager d2interface.FontManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDC6(dc6Path string) (*d2dc6.DC6, error) {
|
// LoadFileStream streams an MPQ file from a source file path
|
||||||
dc6Data, err := LoadFile(dc6Path)
|
func (am *AssetManager) LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
||||||
|
data, err := am.archivedFileManager.LoadFileStream(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
dc6, err := d2dc6.Load(dc6Data)
|
return data, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dc6, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDCC(dccPath string) (*d2dcc.DCC, error) {
|
// LoadFile loads an entire file from a source file path as a []byte
|
||||||
dccData, err := LoadFile(dccPath)
|
func (am *AssetManager) LoadFile(filePath string) ([]byte, error) {
|
||||||
|
data, err := am.archivedFileManager.LoadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return d2dcc.Load(dccData)
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadCOF(cofPath string) (*d2cof.COF, error) {
|
// FileExists checks if a file exists on the underlying file system at the given file path.
|
||||||
cofData, err := LoadFile(cofPath)
|
func (am *AssetManager) FileExists(filePath string) (bool, error) {
|
||||||
if err != nil {
|
return am.archivedFileManager.FileExists(filePath)
|
||||||
return nil, err
|
}
|
||||||
|
|
||||||
|
// LoadAnimation loads an animation by its resource path and its palette path
|
||||||
|
func (am *AssetManager) LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
||||||
|
return am.LoadAnimationWithEffect(animationPath, palettePath, d2enum.DrawEffectNone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAnimationWithEffect loads an animation by its resource path and its palette path with a given transparency value
|
||||||
|
func (am *AssetManager) LoadAnimationWithEffect(animationPath, palettePath string,
|
||||||
|
drawEffect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||||
|
return am.animationManager.LoadAnimation(animationPath, palettePath, drawEffect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||||
|
func (am *AssetManager) LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
||||||
|
c := &Composite{
|
||||||
|
AssetManager: am,
|
||||||
|
baseType: baseType,
|
||||||
|
basePath: baseString(baseType),
|
||||||
|
token: token,
|
||||||
|
palettePath: palettePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
return d2cof.Load(cofData)
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *assetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
// LoadFont loads a font the resource files
|
||||||
|
func (am *AssetManager) LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
||||||
|
return am.fontManager.LoadFont(tablePath, spritePath, palettePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPalette loads a palette from a given palette path
|
||||||
|
func (am *AssetManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||||
|
return am.paletteManager.LoadPalette(palettePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *AssetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
||||||
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
||||||
if verbose {
|
if verbose {
|
||||||
term.OutputInfof("asset manager verbose logging enabled")
|
term.OutputInfof("asset manager verbose logging enabled")
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
// Composite is a composite entity animation
|
// Composite is a composite entity animation
|
||||||
type Composite struct {
|
type Composite struct {
|
||||||
|
*AssetManager
|
||||||
baseType d2enum.ObjectType
|
baseType d2enum.ObjectType
|
||||||
basePath string
|
basePath string
|
||||||
token string
|
token string
|
||||||
@ -28,12 +29,6 @@ type size struct {
|
|||||||
Height int
|
Height int
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateComposite creates a Composite from a given ObjectLookupRecord and palettePath.
|
|
||||||
func CreateComposite(baseType d2enum.ObjectType, token, palettePath string) *Composite {
|
|
||||||
return &Composite{baseType: baseType, basePath: baseString(baseType),
|
|
||||||
token: token, palettePath: palettePath}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance moves the composite animation forward for a given elapsed time in nanoseconds.
|
// Advance moves the composite animation forward for a given elapsed time in nanoseconds.
|
||||||
func (c *Composite) Advance(elapsed float64) error {
|
func (c *Composite) Advance(elapsed float64) error {
|
||||||
if c.mode == nil {
|
if c.mode == nil {
|
||||||
@ -233,11 +228,11 @@ type compositeMode struct {
|
|||||||
|
|
||||||
func (c *Composite) createMode(animationMode animationMode, weaponClass string) (*compositeMode, error) {
|
func (c *Composite) createMode(animationMode animationMode, weaponClass string) (*compositeMode, error) {
|
||||||
cofPath := fmt.Sprintf("%s/%s/COF/%s%s%s.COF", c.basePath, c.token, c.token, animationMode, weaponClass)
|
cofPath := fmt.Sprintf("%s/%s/COF/%s%s%s.COF", c.basePath, c.token, c.token, animationMode, weaponClass)
|
||||||
if exists, _ := FileExists(cofPath); !exists {
|
if exists, _ := c.FileExists(cofPath); !exists {
|
||||||
return nil, errors.New("composite not found")
|
return nil, errors.New("composite not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
cof, err := loadCOF(cofPath)
|
cof, err := c.loadCOF(cofPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -296,8 +291,9 @@ func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weap
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, animationPath := range animationPaths {
|
for _, animationPath := range animationPaths {
|
||||||
if exists, _ := FileExists(animationPath); exists {
|
if exists, _ := c.FileExists(animationPath); exists {
|
||||||
animation, err := LoadAnimationWithEffect(animationPath, palettePath, drawEffect)
|
animation, err := c.LoadAnimationWithEffect(animationPath, palettePath,
|
||||||
|
drawEffect)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return animation, nil
|
return animation, nil
|
||||||
}
|
}
|
||||||
@ -345,6 +341,15 @@ func (c *Composite) updateSize() {
|
|||||||
c.size.Height = biggestH
|
c.size.Height = biggestH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Composite) loadCOF(cofPath string) (*d2cof.COF, error) {
|
||||||
|
cofData, err := c.LoadFile(cofPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d2cof.Load(cofData)
|
||||||
|
}
|
||||||
|
|
||||||
func baseString(baseType d2enum.ObjectType) string {
|
func baseString(baseType d2enum.ObjectType) string {
|
||||||
switch baseType {
|
switch baseType {
|
||||||
case d2enum.ObjectTypePlayer:
|
case d2enum.ObjectTypePlayer:
|
||||||
|
@ -1,90 +1,51 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var singleton *assetManager //nolint:gochecknoglobals // Currently global by design
|
// NewAssetManager creates and assigns all necessary dependencies for the AssetManager top-level functions to work correctly
|
||||||
|
func NewAssetManager(renderer d2interface.Renderer,
|
||||||
|
term d2interface.Terminal) (*AssetManager, error) {
|
||||||
|
|
||||||
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
|
manager := &AssetManager{}
|
||||||
func Initialize(renderer d2interface.Renderer,
|
|
||||||
term d2interface.Terminal) error {
|
|
||||||
var (
|
|
||||||
archiveManager = createArchiveManager(d2config.Config)
|
|
||||||
archivedFileManager = createFileManager(d2config.Config, archiveManager)
|
|
||||||
paletteManager = createPaletteManager()
|
|
||||||
paletteTransformManager = createPaletteTransformManager()
|
|
||||||
animationManager = createAnimationManager(renderer)
|
|
||||||
fontManager = createFontManager()
|
|
||||||
)
|
|
||||||
|
|
||||||
singleton = &assetManager{
|
manager.archiveManager = &archiveManager{
|
||||||
archiveManager,
|
AssetManager: manager,
|
||||||
archivedFileManager,
|
cache: d2cache.CreateCache(archiveBudget),
|
||||||
paletteManager,
|
config: d2config.Config,
|
||||||
paletteTransformManager,
|
|
||||||
animationManager,
|
|
||||||
fontManager,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
manager.archivedFileManager = &fileManager{
|
||||||
|
manager,
|
||||||
|
d2cache.CreateCache(fileBudget),
|
||||||
|
manager.archiveManager,
|
||||||
|
d2config.Config,
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.paletteManager = &paletteManager{
|
||||||
|
manager,
|
||||||
|
d2cache.CreateCache(paletteBudget),
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.paletteTransformManager = &paletteTransformManager{
|
||||||
|
manager,
|
||||||
|
d2cache.CreateCache(paletteTransformBudget),
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.animationManager = &animationManager{
|
||||||
|
AssetManager: manager,
|
||||||
|
renderer: renderer,
|
||||||
|
cache: d2cache.CreateCache(animationBudget),
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.fontManager = &fontManager{manager, d2cache.CreateCache(fontBudget)}
|
||||||
|
|
||||||
if term != nil {
|
if term != nil {
|
||||||
return singleton.BindTerminalCommands(term)
|
return manager, manager.BindTerminalCommands(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return manager, nil
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFileStream streams an MPQ file from a source file path
|
|
||||||
func LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
|
||||||
data, err := singleton.archivedFileManager.LoadFileStream(filePath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFile loads an entire file from a source file path as a []byte
|
|
||||||
func LoadFile(filePath string) ([]byte, error) {
|
|
||||||
data, err := singleton.archivedFileManager.LoadFile(filePath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileExists checks if a file exists on the underlying file system at the given file path.
|
|
||||||
func FileExists(filePath string) (bool, error) {
|
|
||||||
return singleton.archivedFileManager.FileExists(filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAnimation loads an animation by its resource path and its palette path
|
|
||||||
func LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
|
||||||
return LoadAnimationWithEffect(animationPath, palettePath, d2enum.DrawEffectNone)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAnimationWithEffect loads an animation by its resource path and its palette path with a given transparency value
|
|
||||||
func LoadAnimationWithEffect(animationPath, palettePath string,
|
|
||||||
drawEffect d2enum.DrawEffect) (d2interface.Animation, error) {
|
|
||||||
return singleton.animationManager.LoadAnimation(animationPath, palettePath, drawEffect)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
|
||||||
func LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
|
||||||
return CreateComposite(baseType, token, palettePath), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFont loads a font the resource files
|
|
||||||
func LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
|
||||||
return singleton.fontManager.LoadFont(tablePath, spritePath, palettePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPalette loads a palette from a given palette path
|
|
||||||
func LoadPalette(palettePath string) (d2interface.Palette, error) {
|
|
||||||
return singleton.paletteManager.LoadPalette(palettePath)
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package d2asset
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"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"
|
||||||
@ -14,36 +16,11 @@ var _ d2iface.Animation = &DC6Animation{} // Static check to confirm struct conf
|
|||||||
type DC6Animation struct {
|
type DC6Animation struct {
|
||||||
animation
|
animation
|
||||||
dc6Path string
|
dc6Path string
|
||||||
|
dc6 *d2dc6.DC6
|
||||||
palette d2iface.Palette
|
palette d2iface.Palette
|
||||||
renderer d2iface.Renderer
|
renderer d2iface.Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
|
||||||
func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string,
|
|
||||||
palette d2iface.Palette, effect d2enum.DrawEffect) (d2iface.Animation, error) {
|
|
||||||
dc6, err := loadDC6(dc6Path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
anim := DC6Animation{
|
|
||||||
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)
|
|
||||||
|
|
||||||
return &anim, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDirection decodes and sets the direction
|
// SetDirection decodes and sets the direction
|
||||||
func (a *DC6Animation) SetDirection(directionIndex int) error {
|
func (a *DC6Animation) SetDirection(directionIndex int) error {
|
||||||
const smallestInvalidDirectionIndex = 64
|
const smallestInvalidDirectionIndex = 64
|
||||||
@ -66,11 +43,7 @@ func (a *DC6Animation) SetDirection(directionIndex int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *DC6Animation) decodeDirection(directionIndex int) error {
|
func (a *DC6Animation) decodeDirection(directionIndex int) error {
|
||||||
dc6, err := loadDC6(a.dc6Path)
|
dc6 := a.dc6
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
startFrame := directionIndex * int(dc6.FramesPerDirection)
|
startFrame := directionIndex * int(dc6.FramesPerDirection)
|
||||||
|
|
||||||
for i := 0; i < int(dc6.FramesPerDirection); i++ {
|
for i := 0; i < int(dc6.FramesPerDirection); i++ {
|
||||||
|
@ -16,41 +16,12 @@ var _ d2iface.Animation = &DCCAnimation{} // Static check to confirm struct conf
|
|||||||
// DCCAnimation represents an animation decoded from DCC
|
// DCCAnimation represents an animation decoded from DCC
|
||||||
type DCCAnimation struct {
|
type DCCAnimation struct {
|
||||||
animation
|
animation
|
||||||
|
*animationManager
|
||||||
dccPath string
|
dccPath string
|
||||||
palette d2iface.Palette
|
palette d2iface.Palette
|
||||||
renderer d2iface.Renderer
|
renderer d2iface.Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
anim := animation{
|
|
||||||
playLength: defaultPlayLength,
|
|
||||||
playLoop: true,
|
|
||||||
directions: make([]animationDirection, dcc.NumberOfDirections),
|
|
||||||
effect: effect,
|
|
||||||
}
|
|
||||||
|
|
||||||
DCC := DCCAnimation{
|
|
||||||
animation: anim,
|
|
||||||
dccPath: dccPath,
|
|
||||||
palette: palette,
|
|
||||||
renderer: renderer,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = DCC.SetDirection(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DCC, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone creates a copy of the animation
|
// Clone creates a copy of the animation
|
||||||
func (a *DCCAnimation) Clone() d2iface.Animation {
|
func (a *DCCAnimation) Clone() d2iface.Animation {
|
||||||
animation := *a
|
animation := *a
|
||||||
@ -79,7 +50,7 @@ func (a *DCCAnimation) SetDirection(directionIndex int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *DCCAnimation) decodeDirection(directionIndex int) error {
|
func (a *DCCAnimation) decodeDirection(directionIndex int) error {
|
||||||
dcc, err := loadDCC(a.dccPath)
|
dcc, err := a.loadDCC(a.dccPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -25,45 +23,6 @@ type Font struct {
|
|||||||
color color.Color
|
color color.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
|
||||||
sheet, err := LoadAnimation(spritePath, palettePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := LoadFile(tablePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(data[:5]) != "Woo!\x01" {
|
|
||||||
return nil, errors.New("invalid font table format")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, maxCharHeight := sheet.GetFrameBounds()
|
|
||||||
|
|
||||||
glyphs := make(map[rune]fontGlyph)
|
|
||||||
|
|
||||||
for i := 12; i < len(data); i += 14 {
|
|
||||||
code := rune(binary.LittleEndian.Uint16(data[i : i+2]))
|
|
||||||
|
|
||||||
var glyph fontGlyph
|
|
||||||
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
|
||||||
glyph.width = int(data[i+3])
|
|
||||||
glyph.height = maxCharHeight
|
|
||||||
|
|
||||||
glyphs[code] = glyph
|
|
||||||
}
|
|
||||||
|
|
||||||
font := &Font{
|
|
||||||
sheet: sheet,
|
|
||||||
glyphs: glyphs,
|
|
||||||
color: color.White,
|
|
||||||
}
|
|
||||||
|
|
||||||
return font, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetColor sets the fonts color
|
// SetColor sets the fonts color
|
||||||
func (f *Font) SetColor(c color.Color) {
|
func (f *Font) SetColor(c color.Color) {
|
||||||
f.color = c
|
f.color = c
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,13 +18,10 @@ var _ d2interface.FontManager = &fontManager{}
|
|||||||
var _ d2interface.Cacher = &fontManager{}
|
var _ d2interface.Cacher = &fontManager{}
|
||||||
|
|
||||||
type fontManager struct {
|
type fontManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFontManager() d2interface.FontManager {
|
|
||||||
return &fontManager{d2cache.CreateCache(fontBudget)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFont loads a font from the archives managed by the ArchiveManager
|
// LoadFont loads a font from the archives managed by the ArchiveManager
|
||||||
func (fm *fontManager) LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font,
|
func (fm *fontManager) LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font,
|
||||||
error) {
|
error) {
|
||||||
@ -31,7 +30,41 @@ func (fm *fontManager) LoadFont(tablePath, spritePath, palettePath string) (d2in
|
|||||||
return font.(d2interface.Font), nil
|
return font.(d2interface.Font), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
font, err := loadFont(tablePath, spritePath, palettePath)
|
sheet, err := fm.LoadAnimation(spritePath, palettePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := fm.LoadFile(tablePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(data[:5]) != "Woo!\x01" {
|
||||||
|
return nil, errors.New("invalid font table format")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, maxCharHeight := sheet.GetFrameBounds()
|
||||||
|
|
||||||
|
glyphs := make(map[rune]fontGlyph)
|
||||||
|
|
||||||
|
for i := 12; i < len(data); i += 14 {
|
||||||
|
code := rune(binary.LittleEndian.Uint16(data[i : i+2]))
|
||||||
|
|
||||||
|
var glyph fontGlyph
|
||||||
|
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
||||||
|
glyph.width = int(data[i+3])
|
||||||
|
glyph.height = maxCharHeight
|
||||||
|
|
||||||
|
glyphs[code] = glyph
|
||||||
|
}
|
||||||
|
|
||||||
|
font := &Font{
|
||||||
|
sheet: sheet,
|
||||||
|
glyphs: glyphs,
|
||||||
|
color: color.White,
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
@ -11,6 +10,7 @@ var _ d2interface.PaletteManager = &paletteManager{}
|
|||||||
var _ d2interface.Cacher = &paletteManager{}
|
var _ d2interface.Cacher = &paletteManager{}
|
||||||
|
|
||||||
type paletteManager struct {
|
type paletteManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,17 +18,13 @@ const (
|
|||||||
paletteBudget = 64
|
paletteBudget = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
func createPaletteManager() d2interface.PaletteManager {
|
|
||||||
return &paletteManager{d2cache.CreateCache(paletteBudget)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPalette loads a palette from archives managed by the ArchiveManager
|
// LoadPalette loads a palette from archives managed by the ArchiveManager
|
||||||
func (pm *paletteManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
func (pm *paletteManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||||
if palette, found := pm.cache.Retrieve(palettePath); found {
|
if palette, found := pm.cache.Retrieve(palettePath); found {
|
||||||
return palette.(d2interface.Palette), nil
|
return palette.(d2interface.Palette), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
paletteData, err := LoadFile(palettePath)
|
paletteData, err := pm.LoadFile(palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
type paletteTransformManager struct {
|
type paletteTransformManager struct {
|
||||||
|
*AssetManager
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,16 +14,12 @@ const (
|
|||||||
paletteTransformBudget = 64
|
paletteTransformBudget = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
func createPaletteTransformManager() *paletteTransformManager {
|
|
||||||
return &paletteTransformManager{d2cache.CreateCache(paletteTransformBudget)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pm *paletteTransformManager) loadPaletteTransform(path string) (*d2pl2.PL2, error) {
|
func (pm *paletteTransformManager) loadPaletteTransform(path string) (*d2pl2.PL2, error) {
|
||||||
if pl2, found := pm.cache.Retrieve(path); found {
|
if pl2, found := pm.cache.Retrieve(path); found {
|
||||||
return pl2.(*d2pl2.PL2), nil
|
return pl2.(*d2pl2.PL2), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := LoadFile(path)
|
data, err := pm.LoadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ package ebiten
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
|
||||||
@ -15,18 +16,11 @@ const sampleRate = 44100
|
|||||||
|
|
||||||
var _ d2interface.AudioProvider = &AudioProvider{} // Static check to confirm struct conforms to interface
|
var _ d2interface.AudioProvider = &AudioProvider{} // Static check to confirm struct conforms to interface
|
||||||
|
|
||||||
// AudioProvider represents a provider capable of playing audio
|
|
||||||
type AudioProvider struct {
|
|
||||||
audioContext *audio.Context // The Audio context
|
|
||||||
bgmAudio *audio.Player // The audio player
|
|
||||||
lastBgm string
|
|
||||||
sfxVolume float64
|
|
||||||
bgmVolume float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateAudio creates an instance of ebiten's audio provider
|
// CreateAudio creates an instance of ebiten's audio provider
|
||||||
func CreateAudio() (*AudioProvider, error) {
|
func CreateAudio(am *d2asset.AssetManager) (*AudioProvider, error) {
|
||||||
result := &AudioProvider{}
|
result := &AudioProvider{
|
||||||
|
assetManager: am,
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
result.audioContext, err = audio.NewContext(sampleRate)
|
result.audioContext, err = audio.NewContext(sampleRate)
|
||||||
@ -39,6 +33,16 @@ func CreateAudio() (*AudioProvider, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AudioProvider represents a provider capable of playing audio
|
||||||
|
type AudioProvider struct {
|
||||||
|
assetManager *d2asset.AssetManager
|
||||||
|
audioContext *audio.Context // The Audio context
|
||||||
|
bgmAudio *audio.Player // The audio player
|
||||||
|
lastBgm string
|
||||||
|
sfxVolume float64
|
||||||
|
bgmVolume float64
|
||||||
|
}
|
||||||
|
|
||||||
// PlayBGM loads an audio stream and plays it in the background
|
// PlayBGM loads an audio stream and plays it in the background
|
||||||
func (eap *AudioProvider) PlayBGM(song string) {
|
func (eap *AudioProvider) PlayBGM(song string) {
|
||||||
if eap.lastBgm == song {
|
if eap.lastBgm == song {
|
||||||
@ -61,7 +65,7 @@ func (eap *AudioProvider) PlayBGM(song string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
audioStream, err := d2asset.LoadFileStream(song)
|
audioStream, err := eap.assetManager.LoadFileStream(song)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -103,7 +107,7 @@ func (eap *AudioProvider) LoadSound(sfx string, loop, bgm bool) (d2interface.Sou
|
|||||||
volume = eap.bgmVolume
|
volume = eap.bgmVolume
|
||||||
}
|
}
|
||||||
|
|
||||||
result := CreateSoundEffect(sfx, eap.audioContext, loop)
|
result := eap.createSoundEffect(sfx, eap.audioContext, loop)
|
||||||
|
|
||||||
result.volumeScale = volume
|
result.volumeScale = volume
|
||||||
result.SetVolume(volume)
|
result.SetVolume(volume)
|
||||||
@ -116,3 +120,53 @@ func (eap *AudioProvider) SetVolumes(bgmVolume, sfxVolume float64) {
|
|||||||
eap.sfxVolume = sfxVolume
|
eap.sfxVolume = sfxVolume
|
||||||
eap.bgmVolume = bgmVolume
|
eap.bgmVolume = bgmVolume
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createSoundEffect creates a new instance of ebiten's sound effect implementation.
|
||||||
|
func (eap *AudioProvider) createSoundEffect(sfx string, context *audio.Context,
|
||||||
|
loop bool) *SoundEffect {
|
||||||
|
result := &SoundEffect{}
|
||||||
|
|
||||||
|
soundFile := "/data/global/sfx/"
|
||||||
|
|
||||||
|
if _, exists := d2datadict.Sounds[sfx]; exists {
|
||||||
|
soundEntry := d2datadict.Sounds[sfx]
|
||||||
|
soundFile += soundEntry.FileName
|
||||||
|
} else {
|
||||||
|
soundFile += sfx
|
||||||
|
}
|
||||||
|
|
||||||
|
audioData, err := eap.assetManager.LoadFileStream(soundFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
audioData, err = eap.assetManager.LoadFileStream("/data/global/music/" + sfx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := wav.Decode(context, audioData)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var player *audio.Player
|
||||||
|
|
||||||
|
if loop {
|
||||||
|
s := audio.NewInfiniteLoop(d, d.Length())
|
||||||
|
result.panStream = newPanStreamFromReader(s)
|
||||||
|
player, err = audio.NewPlayer(context, result.panStream)
|
||||||
|
} else {
|
||||||
|
result.panStream = newPanStreamFromReader(d)
|
||||||
|
player, err = audio.NewPlayer(context, result.panStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.player = player
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/audio"
|
"github.com/hajimehoshi/ebiten/audio"
|
||||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type panStream struct {
|
type panStream struct {
|
||||||
@ -56,55 +51,6 @@ type SoundEffect struct {
|
|||||||
panStream *panStream
|
panStream *panStream
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSoundEffect creates a new instance of ebiten's sound effect implementation.
|
|
||||||
func CreateSoundEffect(sfx string, context *audio.Context, loop bool) *SoundEffect {
|
|
||||||
result := &SoundEffect{}
|
|
||||||
|
|
||||||
soundFile := "/data/global/sfx/"
|
|
||||||
|
|
||||||
if _, exists := d2datadict.Sounds[sfx]; exists {
|
|
||||||
soundEntry := d2datadict.Sounds[sfx]
|
|
||||||
soundFile += soundEntry.FileName
|
|
||||||
} else {
|
|
||||||
soundFile += sfx
|
|
||||||
}
|
|
||||||
|
|
||||||
audioData, err := d2asset.LoadFileStream(soundFile)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
audioData, err = d2asset.LoadFileStream("/data/global/music/" + sfx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := wav.Decode(context, audioData)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var player *audio.Player
|
|
||||||
|
|
||||||
if loop {
|
|
||||||
s := audio.NewInfiniteLoop(d, d.Length())
|
|
||||||
result.panStream = newPanStreamFromReader(s)
|
|
||||||
player, err = audio.NewPlayer(context, result.panStream)
|
|
||||||
} else {
|
|
||||||
result.panStream = newPanStreamFromReader(d)
|
|
||||||
player, err = audio.NewPlayer(context, result.panStream)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result.player = player
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetPan sets the audio pan, left is -1.0, center is 0.0, right is 1.0
|
// SetPan sets the audio pan, left is -1.0, center is 0.0, right is 1.0
|
||||||
func (v *SoundEffect) SetPan(pan float64) {
|
func (v *SoundEffect) SetPan(pan float64) {
|
||||||
v.panStream.pan = pan
|
v.panStream.pan = pan
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package d2gui
|
package d2gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type buttonState int
|
type buttonState int
|
||||||
@ -30,90 +26,6 @@ type Button struct {
|
|||||||
surfaces []d2interface.Surface
|
surfaces []d2interface.Surface
|
||||||
}
|
}
|
||||||
|
|
||||||
func createButton(renderer d2interface.Renderer, text string, buttonStyle ButtonStyle) (*Button, error) {
|
|
||||||
config := getButtonStyleConfig(buttonStyle)
|
|
||||||
if config == nil {
|
|
||||||
return nil, errors.New("invalid button style")
|
|
||||||
}
|
|
||||||
|
|
||||||
animation, loadErr := d2asset.LoadAnimation(config.animationPath, config.palettePath)
|
|
||||||
if loadErr != nil {
|
|
||||||
return nil, loadErr
|
|
||||||
}
|
|
||||||
|
|
||||||
var buttonWidth int
|
|
||||||
|
|
||||||
for i := 0; i < config.segmentsX; i++ {
|
|
||||||
w, _, err := animation.GetFrameSize(i)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buttonWidth += w
|
|
||||||
}
|
|
||||||
|
|
||||||
var buttonHeight int
|
|
||||||
|
|
||||||
for i := 0; i < config.segmentsY; i++ {
|
|
||||||
_, h, err := animation.GetFrameSize(i * config.segmentsY)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buttonHeight += h
|
|
||||||
}
|
|
||||||
|
|
||||||
font, loadErr := loadFont(config.fontStyle)
|
|
||||||
if loadErr != nil {
|
|
||||||
return nil, loadErr
|
|
||||||
}
|
|
||||||
|
|
||||||
textColor := rgbaColor(grey)
|
|
||||||
textWidth, textHeight := font.GetTextMetrics(text)
|
|
||||||
textX := half(buttonWidth) - half(textWidth)
|
|
||||||
textY := half(buttonHeight) - half(textHeight) + config.textOffset
|
|
||||||
|
|
||||||
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
|
|
||||||
surfaces := make([]d2interface.Surface, surfaceCount)
|
|
||||||
|
|
||||||
for i := 0; i < surfaceCount; i++ {
|
|
||||||
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
|
|
||||||
if surfaceErr != nil {
|
|
||||||
return nil, surfaceErr
|
|
||||||
}
|
|
||||||
|
|
||||||
segX, segY, frame := config.segmentsX, config.segmentsY, i
|
|
||||||
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
|
|
||||||
return nil, segErr
|
|
||||||
}
|
|
||||||
|
|
||||||
font.SetColor(textColor)
|
|
||||||
|
|
||||||
var textOffsetX, textOffsetY int
|
|
||||||
|
|
||||||
switch buttonState(i) {
|
|
||||||
case buttonStatePressed, buttonStatePressedToggled:
|
|
||||||
textOffsetX = -2
|
|
||||||
textOffsetY = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
|
|
||||||
surfaceErr = font.RenderText(text, surface)
|
|
||||||
surface.Pop()
|
|
||||||
|
|
||||||
if surfaceErr != nil {
|
|
||||||
return nil, surfaceErr
|
|
||||||
}
|
|
||||||
|
|
||||||
surfaces[i] = surface
|
|
||||||
}
|
|
||||||
|
|
||||||
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
|
|
||||||
button.SetVisible(true)
|
|
||||||
|
|
||||||
return button, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Button) onMouseButtonDown(_ d2interface.MouseEvent) bool {
|
func (b *Button) onMouseButtonDown(_ d2interface.MouseEvent) bool {
|
||||||
b.state = buttonStatePressed
|
b.state = buttonStatePressed
|
||||||
return false
|
return false
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func loadFont(fontStyle FontStyle) (d2interface.Font, error) {
|
func loadFont(fontStyle FontStyle) (d2interface.Font, error) {
|
||||||
@ -15,7 +14,8 @@ func loadFont(fontStyle FontStyle) (d2interface.Font, error) {
|
|||||||
return nil, errors.New("invalid font style")
|
return nil, errors.New("invalid font style")
|
||||||
}
|
}
|
||||||
|
|
||||||
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
|
return singleton.asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6",
|
||||||
|
config.palettePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderSegmented(animation d2interface.Animation, segmentsX, segmentsY, frameOffset int,
|
func renderSegmented(animation d2interface.Animation, segmentsX, segmentsY, frameOffset int,
|
||||||
|
@ -3,6 +3,8 @@ package d2gui
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,11 +16,11 @@ var (
|
|||||||
var singleton *manager // nolint:gochecknoglobals // currently global by design
|
var singleton *manager // nolint:gochecknoglobals // currently global by design
|
||||||
|
|
||||||
// Initialize creates a singleton gui manager
|
// Initialize creates a singleton gui manager
|
||||||
func Initialize(inputManager d2interface.InputManager) error {
|
func Initialize(asset *d2asset.AssetManager, inputManager d2interface.InputManager) error {
|
||||||
verifyNotInit()
|
verifyNotInit()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if singleton, err = createGuiManager(inputManager); err != nil {
|
if singleton, err = createGuiManager(asset, inputManager); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,13 @@
|
|||||||
package d2gui
|
package d2gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||||
)
|
)
|
||||||
|
|
||||||
type layoutEntry struct {
|
|
||||||
widget widget
|
|
||||||
|
|
||||||
x int
|
|
||||||
y int
|
|
||||||
width int
|
|
||||||
height int
|
|
||||||
|
|
||||||
mouseOver bool
|
|
||||||
mouseDown [3]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
const layoutDebug = false // turns on debug rendering stuff for layouts
|
const layoutDebug = false // turns on debug rendering stuff for layouts
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -168,7 +158,7 @@ func (l *Layout) AddLabel(text string, fontStyle FontStyle) (*Label, error) {
|
|||||||
|
|
||||||
// AddButton given a string and ButtonStyle, adds a button as a layout entry
|
// AddButton given a string and ButtonStyle, adds a button as a layout entry
|
||||||
func (l *Layout) AddButton(text string, buttonStyle ButtonStyle) (*Button, error) {
|
func (l *Layout) AddButton(text string, buttonStyle ButtonStyle) (*Button, error) {
|
||||||
button, err := createButton(l.renderer, text, buttonStyle)
|
button, err := l.createButton(l.renderer, text, buttonStyle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -421,10 +411,88 @@ func (l *Layout) handleEntryVerticalAlign(width int, entry *layoutEntry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIn layout entry, spc. of an event.
|
func (l *Layout) createButton(renderer d2interface.Renderer, text string,
|
||||||
func (l *layoutEntry) IsIn(event d2interface.HandlerEvent) bool {
|
buttonStyle ButtonStyle) (*Button,
|
||||||
sx, sy := l.widget.ScreenPos()
|
error) {
|
||||||
rect := d2geom.Rectangle{Left: sx, Top: sy, Width: l.width, Height: l.height}
|
config := getButtonStyleConfig(buttonStyle)
|
||||||
|
if config == nil {
|
||||||
|
return nil, errors.New("invalid button style")
|
||||||
|
}
|
||||||
|
|
||||||
return rect.IsInRect(event.X(), event.Y())
|
animation, loadErr := singleton.asset.LoadAnimation(config.animationPath, config.palettePath)
|
||||||
|
if loadErr != nil {
|
||||||
|
return nil, loadErr
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonWidth int
|
||||||
|
|
||||||
|
for i := 0; i < config.segmentsX; i++ {
|
||||||
|
w, _, err := animation.GetFrameSize(i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonWidth += w
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonHeight int
|
||||||
|
|
||||||
|
for i := 0; i < config.segmentsY; i++ {
|
||||||
|
_, h, err := animation.GetFrameSize(i * config.segmentsY)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonHeight += h
|
||||||
|
}
|
||||||
|
|
||||||
|
font, loadErr := loadFont(config.fontStyle)
|
||||||
|
if loadErr != nil {
|
||||||
|
return nil, loadErr
|
||||||
|
}
|
||||||
|
|
||||||
|
textColor := rgbaColor(grey)
|
||||||
|
textWidth, textHeight := font.GetTextMetrics(text)
|
||||||
|
textX := half(buttonWidth) - half(textWidth)
|
||||||
|
textY := half(buttonHeight) - half(textHeight) + config.textOffset
|
||||||
|
|
||||||
|
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
|
||||||
|
surfaces := make([]d2interface.Surface, surfaceCount)
|
||||||
|
|
||||||
|
for i := 0; i < surfaceCount; i++ {
|
||||||
|
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
|
||||||
|
if surfaceErr != nil {
|
||||||
|
return nil, surfaceErr
|
||||||
|
}
|
||||||
|
|
||||||
|
segX, segY, frame := config.segmentsX, config.segmentsY, i
|
||||||
|
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
|
||||||
|
return nil, segErr
|
||||||
|
}
|
||||||
|
|
||||||
|
font.SetColor(textColor)
|
||||||
|
|
||||||
|
var textOffsetX, textOffsetY int
|
||||||
|
|
||||||
|
switch buttonState(i) {
|
||||||
|
case buttonStatePressed, buttonStatePressedToggled:
|
||||||
|
textOffsetX = -2
|
||||||
|
textOffsetY = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
|
||||||
|
surfaceErr = font.RenderText(text, surface)
|
||||||
|
surface.Pop()
|
||||||
|
|
||||||
|
if surfaceErr != nil {
|
||||||
|
return nil, surfaceErr
|
||||||
|
}
|
||||||
|
|
||||||
|
surfaces[i] = surface
|
||||||
|
}
|
||||||
|
|
||||||
|
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
|
||||||
|
button.SetVisible(true)
|
||||||
|
|
||||||
|
return button, nil
|
||||||
}
|
}
|
||||||
|
26
d2core/d2gui/layout_entry.go
Normal file
26
d2core/d2gui/layout_entry.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package d2gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
)
|
||||||
|
|
||||||
|
type layoutEntry struct {
|
||||||
|
widget widget
|
||||||
|
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
|
||||||
|
mouseOver bool
|
||||||
|
mouseDown [3]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIn layout entry, spc. of an event.
|
||||||
|
func (l *layoutEntry) IsIn(event d2interface.HandlerEvent) bool {
|
||||||
|
sx, sy := l.widget.ScreenPos()
|
||||||
|
rect := d2geom.Rectangle{Left: sx, Top: sy, Width: l.width, Height: l.height}
|
||||||
|
|
||||||
|
return rect.IsInRect(event.X(), event.Y())
|
||||||
|
}
|
@ -5,12 +5,12 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type manager struct {
|
type manager struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
layout *Layout
|
layout *Layout
|
||||||
cursorAnim d2interface.Animation
|
cursorAnim d2interface.Animation
|
||||||
cursorX int
|
cursorX int
|
||||||
@ -20,18 +20,19 @@ type manager struct {
|
|||||||
loading bool
|
loading bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func createGuiManager(inputManager d2interface.InputManager) (*manager, error) {
|
func createGuiManager(asset *d2asset.AssetManager, inputManager d2interface.InputManager) (*manager, error) {
|
||||||
cursorAnim, err := d2asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
|
cursorAnim, err := asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingAnim, err := d2asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading)
|
loadingAnim, err := asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manager := &manager{
|
manager := &manager{
|
||||||
|
asset: asset,
|
||||||
cursorAnim: cursorAnim,
|
cursorAnim: cursorAnim,
|
||||||
loadingAnim: loadingAnim,
|
loadingAnim: loadingAnim,
|
||||||
cursorVisible: true,
|
cursorVisible: true,
|
||||||
|
@ -3,7 +3,6 @@ package d2gui
|
|||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AnimationDirection is a the animation play direction
|
// AnimationDirection is a the animation play direction
|
||||||
@ -32,7 +31,7 @@ type AnimatedSprite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createSprite(imagePath, palettePath string) (*Sprite, error) {
|
func createSprite(imagePath, palettePath string) (*Sprite, error) {
|
||||||
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
|
animation, err := singleton.asset.LoadAnimation(imagePath, palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -45,7 +44,7 @@ func createSprite(imagePath, palettePath string) (*Sprite, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createAnimatedSprite(imagePath, palettePath string, direction AnimationDirection) (*AnimatedSprite, error) {
|
func createAnimatedSprite(imagePath, palettePath string, direction AnimationDirection) (*AnimatedSprite, error) {
|
||||||
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
|
animation, err := singleton.asset.LoadAnimation(imagePath, palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||||
@ -16,6 +18,9 @@ import (
|
|||||||
|
|
||||||
// MapEngine loads the tiles which make up the isometric map and the entities
|
// MapEngine loads the tiles which make up the isometric map and the entities
|
||||||
type MapEngine struct {
|
type MapEngine struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
|
*d2mapstamp.StampFactory
|
||||||
|
*d2mapentity.MapEntityFactory
|
||||||
seed int64 // The map seed
|
seed int64 // The map seed
|
||||||
entities map[string]d2interface.MapEntity // Entities on the map
|
entities map[string]d2interface.MapEntity // Entities on the map
|
||||||
tiles []MapTile
|
tiles []MapTile
|
||||||
@ -28,8 +33,16 @@ type MapEngine struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
func CreateMapEngine(asset *d2asset.AssetManager) *MapEngine {
|
||||||
engine := &MapEngine{}
|
entity := d2mapentity.NewMapEntityFactory(asset)
|
||||||
|
stamp := d2mapstamp.NewStampFactory(asset, entity)
|
||||||
|
|
||||||
|
engine := &MapEngine{
|
||||||
|
asset: asset,
|
||||||
|
MapEntityFactory: entity,
|
||||||
|
StampFactory: stamp,
|
||||||
|
}
|
||||||
|
|
||||||
return engine
|
return engine
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +77,7 @@ func (m *MapEngine) addDT1(fileName string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + fileName)
|
fileData, err := m.asset.LoadFile("/data/global/tiles/" + fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not load /data/global/tiles/%s", fileName)
|
log.Printf("Could not load /data/global/tiles/%s", fileName)
|
||||||
// panic(err)
|
// panic(err)
|
||||||
@ -84,7 +97,7 @@ func (m *MapEngine) AddDS1(fileName string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + fileName)
|
fileData, err := m.asset.LoadFile("/data/global/tiles/" + fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -289,7 +302,7 @@ func (m *MapEngine) TileExists(tileX, tileY int) bool {
|
|||||||
|
|
||||||
// GenerateMap clears the map and places the specified stamp.
|
// GenerateMap clears the map and places the specified stamp.
|
||||||
func (m *MapEngine) GenerateMap(regionType d2enum.RegionIdType, levelPreset, fileIndex int) {
|
func (m *MapEngine) GenerateMap(regionType d2enum.RegionIdType, levelPreset, fileIndex int) {
|
||||||
region := d2mapstamp.LoadStamp(regionType, levelPreset, fileIndex)
|
region := m.LoadStamp(regionType, levelPreset, fileIndex)
|
||||||
regionSize := region.Size()
|
regionSize := region.Size()
|
||||||
m.ResetMap(regionType, regionSize.Width, regionSize.Height)
|
m.ResetMap(regionType, regionSize.Width, regionSize.Height)
|
||||||
m.PlaceStamp(region, 0, 0)
|
m.PlaceStamp(region, 0, 0)
|
||||||
|
@ -4,6 +4,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||||
@ -15,6 +18,16 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2item/diablo2item"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2item/diablo2item"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewMapEntityFactory creates a MapEntityFactory instance with the given asset manager
|
||||||
|
func NewMapEntityFactory(asset *d2asset.AssetManager) *MapEntityFactory {
|
||||||
|
return &MapEntityFactory{asset}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapEntityFactory creates map entities for the MapEngine
|
||||||
|
type MapEntityFactory struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
|
}
|
||||||
|
|
||||||
// NewAnimatedEntity creates an instance of AnimatedEntity
|
// NewAnimatedEntity creates an instance of AnimatedEntity
|
||||||
func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntity {
|
func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntity {
|
||||||
entity := &AnimatedEntity{
|
entity := &AnimatedEntity{
|
||||||
@ -27,7 +40,7 @@ func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewPlayer creates a new player entity and returns a pointer to it.
|
// NewPlayer creates a new player entity and returns a pointer to it.
|
||||||
func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||||
stats *d2hero.HeroStatsState, equipment *d2inventory.CharacterEquipment) *Player {
|
stats *d2hero.HeroStatsState, equipment *d2inventory.CharacterEquipment) *Player {
|
||||||
layerEquipment := &[d2enum.CompositeTypeMax]string{
|
layerEquipment := &[d2enum.CompositeTypeMax]string{
|
||||||
d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(),
|
d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(),
|
||||||
@ -40,7 +53,7 @@ func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
|||||||
d2enum.CompositeTypeShield: equipment.Shield.GetItemCode(),
|
d2enum.CompositeTypeShield: equipment.Shield.GetItemCode(),
|
||||||
}
|
}
|
||||||
|
|
||||||
composite, err := d2asset.LoadComposite(d2enum.ObjectTypePlayer, heroType.GetToken(),
|
composite, err := f.asset.LoadComposite(d2enum.ObjectTypePlayer, heroType.GetToken(),
|
||||||
d2resource.PaletteUnits)
|
d2resource.PaletteUnits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -81,8 +94,8 @@ func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMissile creates a new Missile and initializes it's animation.
|
// NewMissile creates a new Missile and initializes it's animation.
|
||||||
func NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
func (f *MapEntityFactory) NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
||||||
animation, err := d2asset.LoadAnimation(
|
animation, err := f.asset.LoadAnimation(
|
||||||
fmt.Sprintf("%s/%s.dcc", d2resource.MissileData, record.Animation.CelFileName),
|
fmt.Sprintf("%s/%s.dcc", d2resource.MissileData, record.Animation.CelFileName),
|
||||||
d2resource.PaletteUnits,
|
d2resource.PaletteUnits,
|
||||||
)
|
)
|
||||||
@ -109,7 +122,7 @@ func NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewItem creates an item map entity
|
// NewItem creates an item map entity
|
||||||
func NewItem(x, y int, codes ...string) (*Item, error) {
|
func (f *MapEntityFactory) NewItem(x, y int, codes ...string) (*Item, error) {
|
||||||
item := diablo2item.NewItem(codes...)
|
item := diablo2item.NewItem(codes...)
|
||||||
|
|
||||||
if item == nil {
|
if item == nil {
|
||||||
@ -118,7 +131,7 @@ func NewItem(x, y int, codes ...string) (*Item, error) {
|
|||||||
|
|
||||||
filename := item.CommonRecord().FlippyFile
|
filename := item.CommonRecord().FlippyFile
|
||||||
filepath := fmt.Sprintf("%s/%s.DC6", d2resource.ItemGraphics, filename)
|
filepath := fmt.Sprintf("%s/%s.DC6", d2resource.ItemGraphics, filename)
|
||||||
animation, err := d2asset.LoadAnimation(filepath, d2resource.PaletteUnits)
|
animation, err := f.asset.LoadAnimation(filepath, d2resource.PaletteUnits)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -137,7 +150,7 @@ func NewItem(x, y int, codes ...string) (*Item, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewNPC creates a new NPC and returns a pointer to it.
|
// NewNPC creates a new NPC and returns a pointer to it.
|
||||||
func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC, error) {
|
func (f *MapEntityFactory) NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC, error) {
|
||||||
result := &NPC{
|
result := &NPC{
|
||||||
mapEntity: newMapEntity(x, y),
|
mapEntity: newMapEntity(x, y),
|
||||||
HasPaths: false,
|
HasPaths: false,
|
||||||
@ -151,7 +164,7 @@ func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC,
|
|||||||
equipment[compType] = selectEquip(opts)
|
equipment[compType] = selectEquip(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
composite, _ := d2asset.LoadComposite(d2enum.ObjectTypeCharacter, monstat.AnimationDirectoryToken,
|
composite, _ := f.asset.LoadComposite(d2enum.ObjectTypeCharacter, monstat.AnimationDirectoryToken,
|
||||||
d2resource.PaletteUnits)
|
d2resource.PaletteUnits)
|
||||||
result.composite = composite
|
result.composite = composite
|
||||||
|
|
||||||
@ -175,3 +188,30 @@ func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC,
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewObject creates an instance of AnimatedComposite
|
||||||
|
func (f *MapEntityFactory) NewObject(x, y int, objectRec *d2datadict.ObjectRecord,
|
||||||
|
palettePath string) (*Object, error) {
|
||||||
|
locX, locY := float64(x), float64(y)
|
||||||
|
entity := &Object{
|
||||||
|
uuid: uuid.NewV4().String(),
|
||||||
|
objectRecord: objectRec,
|
||||||
|
Position: d2vector.NewPosition(locX, locY),
|
||||||
|
name: d2tbl.TranslateString(objectRec.Name),
|
||||||
|
}
|
||||||
|
objectType := &d2datadict.ObjectTypes[objectRec.Index]
|
||||||
|
|
||||||
|
composite, err := f.asset.LoadComposite(d2enum.ObjectTypeItem, objectType.Token,
|
||||||
|
palettePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.composite = composite
|
||||||
|
|
||||||
|
entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false)
|
||||||
|
|
||||||
|
initObject(entity)
|
||||||
|
|
||||||
|
return entity, nil
|
||||||
|
}
|
@ -1,18 +1,14 @@
|
|||||||
// Package d2object implements objects placed on the map and their functionality
|
// Package d2object implements objects placed on the map and their functionality
|
||||||
package d2object
|
package d2mapentity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,36 +24,6 @@ type Object struct {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateObject creates an instance of AnimatedComposite
|
|
||||||
func CreateObject(x, y int, objectRec *d2datadict.ObjectRecord, palettePath string) (*Object, error) {
|
|
||||||
locX, locY := float64(x), float64(y)
|
|
||||||
entity := &Object{
|
|
||||||
uuid: uuid.NewV4().String(),
|
|
||||||
objectRecord: objectRec,
|
|
||||||
Position: d2vector.NewPosition(locX, locY),
|
|
||||||
name: d2tbl.TranslateString(objectRec.Name),
|
|
||||||
}
|
|
||||||
objectType := &d2datadict.ObjectTypes[objectRec.Index]
|
|
||||||
|
|
||||||
composite, err := d2asset.LoadComposite(d2enum.ObjectTypeItem, objectType.Token,
|
|
||||||
d2resource.PaletteUnits)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.composite = composite
|
|
||||||
|
|
||||||
if err := entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := initObject(entity); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return entity, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setMode changes the graphical mode of this animated entity
|
// setMode changes the graphical mode of this animated entity
|
||||||
func (ob *Object) setMode(animationMode d2enum.ObjectAnimationMode, direction int, randomFrame bool) error {
|
func (ob *Object) setMode(animationMode d2enum.ObjectAnimationMode, direction int, randomFrame bool) error {
|
||||||
err := ob.composite.SetMode(animationMode, "HTH")
|
err := ob.composite.SetMode(animationMode, "HTH")
|
@ -1,4 +1,4 @@
|
|||||||
package d2object
|
package d2mapentity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
@ -1,4 +1,3 @@
|
|||||||
//nolint:gomnd
|
|
||||||
package d2mapgen
|
package d2mapgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -20,7 +19,7 @@ func loadPreset(mapEngine *d2mapengine.MapEngine, id, index int) *d2mapstamp.Sta
|
|||||||
mapEngine.AddDS1(file)
|
mapEngine.AddDS1(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d2mapstamp.LoadStamp(d2enum.RegionAct1Wilderness, id, index)
|
return mapEngine.LoadStamp(d2enum.RegionAct1Wilderness, id, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateAct1Overworld generates the map and entities for the first town and surrounding area.
|
// GenerateAct1Overworld generates the map and entities for the first town and surrounding area.
|
||||||
@ -33,7 +32,7 @@ func GenerateAct1Overworld(mapEngine *d2mapengine.MapEngine) {
|
|||||||
mapWidth := mapEngine.Size().Width
|
mapWidth := mapEngine.Size().Width
|
||||||
mapHeight := mapEngine.Size().Height
|
mapHeight := mapEngine.Size().Height
|
||||||
|
|
||||||
townStamp := d2mapstamp.LoadStamp(d2enum.RegionAct1Town, 1, -1)
|
townStamp := mapEngine.LoadStamp(d2enum.RegionAct1Town, 1, -1)
|
||||||
townStamp.RegionPath()
|
townStamp.RegionPath()
|
||||||
townSize := townStamp.Size()
|
townSize := townStamp.Size()
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ const (
|
|||||||
|
|
||||||
// MapRenderer manages the game viewport and Camera. It requests tile and entity data from MapEngine and renders it.
|
// MapRenderer manages the game viewport and Camera. It requests tile and entity data from MapEngine and renders it.
|
||||||
type MapRenderer struct {
|
type MapRenderer struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
renderer d2interface.Renderer // Used for drawing operations
|
renderer d2interface.Renderer // Used for drawing operations
|
||||||
mapEngine *d2mapengine.MapEngine // The map engine that is being rendered
|
mapEngine *d2mapengine.MapEngine // The map engine that is being rendered
|
||||||
palette d2interface.Palette // The palette used for this map
|
palette d2interface.Palette // The palette used for this map
|
||||||
@ -61,9 +62,11 @@ type MapRenderer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateMapRenderer creates a new MapRenderer, sets the required fields and returns a pointer to it.
|
// CreateMapRenderer creates a new MapRenderer, sets the required fields and returns a pointer to it.
|
||||||
func CreateMapRenderer(renderer d2interface.Renderer, mapEngine *d2mapengine.MapEngine,
|
func CreateMapRenderer(asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||||
|
mapEngine *d2mapengine.MapEngine,
|
||||||
term d2interface.Terminal, startX, startY float64) *MapRenderer {
|
term d2interface.Terminal, startX, startY float64) *MapRenderer {
|
||||||
result := &MapRenderer{
|
result := &MapRenderer{
|
||||||
|
asset: asset,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
mapEngine: mapEngine,
|
mapEngine: mapEngine,
|
||||||
viewport: NewViewport(0, 0, 800, 600),
|
viewport: NewViewport(0, 0, 800, 600),
|
||||||
@ -563,7 +566,8 @@ func (mr *MapRenderer) Advance(elapsed float64) {
|
|||||||
mr.Camera.Advance(elapsed)
|
mr.Camera.Advance(elapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette, error) {
|
func (mr *MapRenderer) loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette,
|
||||||
|
error) {
|
||||||
var palettePath string
|
var palettePath string
|
||||||
|
|
||||||
switch levelType {
|
switch levelType {
|
||||||
@ -586,7 +590,7 @@ func loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette, erro
|
|||||||
return nil, errors.New("failed to find palette for region")
|
return nil, errors.New("failed to find palette for region")
|
||||||
}
|
}
|
||||||
|
|
||||||
return d2asset.LoadPalette(palettePath)
|
return mr.asset.LoadPalette(palettePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewportToLeft moves the viewport to the left.
|
// ViewportToLeft moves the viewport to the left.
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (mr *MapRenderer) generateTileCache() {
|
func (mr *MapRenderer) generateTileCache() {
|
||||||
mr.palette, _ = loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
|
mr.palette, _ = mr.loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
|
||||||
|
|
||||||
tiles := *mr.mapEngine.Tiles()
|
tiles := *mr.mapEngine.Tiles()
|
||||||
for idx := range tiles {
|
for idx := range tiles {
|
||||||
|
74
d2core/d2map/d2mapstamp/factory.go
Normal file
74
d2core/d2map/d2mapstamp/factory.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package d2mapstamp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewStampFactory(asset *d2asset.AssetManager, entity *d2mapentity.MapEntityFactory) *StampFactory {
|
||||||
|
return &StampFactory{asset, entity}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StampFactory struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
|
entity *d2mapentity.MapEntityFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadStamp loads the Stamp data from file.
|
||||||
|
func (f *StampFactory) LoadStamp(levelType d2enum.RegionIdType, levelPreset, fileIndex int) *Stamp {
|
||||||
|
stamp := &Stamp{
|
||||||
|
entity: f.entity,
|
||||||
|
regionID: levelType,
|
||||||
|
levelType: d2datadict.LevelTypes[levelType],
|
||||||
|
levelPreset: d2datadict.LevelPresets[levelPreset],
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, levelTypeDt1 := range &stamp.levelType.Files {
|
||||||
|
if levelTypeDt1 != "" && levelTypeDt1 != "0" {
|
||||||
|
fileData, err := f.asset.LoadFile("/data/global/tiles/" + levelTypeDt1)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dt1, _ := d2dt1.LoadDT1(fileData)
|
||||||
|
|
||||||
|
stamp.tiles = append(stamp.tiles, dt1.Tiles...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var levelFilesToPick []string
|
||||||
|
|
||||||
|
for _, fileRecord := range stamp.levelPreset.Files {
|
||||||
|
if fileRecord != "" && fileRecord != "0" {
|
||||||
|
levelFilesToPick = append(levelFilesToPick, fileRecord)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * rand.Float64()))
|
||||||
|
if fileIndex >= 0 && fileIndex < len(levelFilesToPick) {
|
||||||
|
levelIndex = fileIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
if levelFilesToPick == nil {
|
||||||
|
panic("no level files to pick from")
|
||||||
|
}
|
||||||
|
|
||||||
|
stamp.regionPath = levelFilesToPick[levelIndex]
|
||||||
|
fileData, err := f.asset.LoadFile("/data/global/tiles/" + stamp.regionPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stamp.ds1, _ = d2ds1.LoadDS1(fileData)
|
||||||
|
|
||||||
|
return stamp
|
||||||
|
}
|
@ -1,9 +1,6 @@
|
|||||||
package d2mapstamp
|
package d2mapstamp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||||
@ -13,13 +10,16 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2object"
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
subtilesPerTile = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
|
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
|
||||||
type Stamp struct {
|
type Stamp struct {
|
||||||
|
entity *d2mapentity.MapEntityFactory
|
||||||
regionPath string // The file path of the region
|
regionPath string // The file path of the region
|
||||||
regionID d2enum.RegionIdType
|
regionID d2enum.RegionIdType
|
||||||
levelType d2datadict.LevelTypeRecord // The level type id for this stamp
|
levelType d2datadict.LevelTypeRecord // The level type id for this stamp
|
||||||
@ -28,56 +28,6 @@ type Stamp struct {
|
|||||||
ds1 *d2ds1.DS1 // The backing DS1 file for this stamp
|
ds1 *d2ds1.DS1 // The backing DS1 file for this stamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadStamp loads the Stamp data from file.
|
|
||||||
func LoadStamp(levelType d2enum.RegionIdType, levelPreset, fileIndex int) *Stamp {
|
|
||||||
stamp := &Stamp{
|
|
||||||
regionID: levelType,
|
|
||||||
levelType: d2datadict.LevelTypes[levelType],
|
|
||||||
levelPreset: d2datadict.LevelPresets[levelPreset],
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, levelTypeDt1 := range &stamp.levelType.Files {
|
|
||||||
if levelTypeDt1 != "" && levelTypeDt1 != "0" {
|
|
||||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + levelTypeDt1)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dt1, _ := d2dt1.LoadDT1(fileData)
|
|
||||||
|
|
||||||
stamp.tiles = append(stamp.tiles, dt1.Tiles...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var levelFilesToPick []string
|
|
||||||
|
|
||||||
for _, fileRecord := range stamp.levelPreset.Files {
|
|
||||||
if fileRecord != "" && fileRecord != "0" {
|
|
||||||
levelFilesToPick = append(levelFilesToPick, fileRecord)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * rand.Float64()))
|
|
||||||
if fileIndex >= 0 && fileIndex < len(levelFilesToPick) {
|
|
||||||
levelIndex = fileIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
if levelFilesToPick == nil {
|
|
||||||
panic("no level files to pick from")
|
|
||||||
}
|
|
||||||
|
|
||||||
stamp.regionPath = levelFilesToPick[levelIndex]
|
|
||||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + stamp.regionPath)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stamp.ds1, _ = d2ds1.LoadDS1(fileData)
|
|
||||||
|
|
||||||
return stamp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of the stamp in tiles.
|
// Size returns the size of the stamp in tiles.
|
||||||
func (mr *Stamp) Size() d2geom.Size {
|
func (mr *Stamp) Size() d2geom.Size {
|
||||||
return d2geom.Size{Width: int(mr.ds1.Width), Height: int(mr.ds1.Height)}
|
return d2geom.Size{Width: int(mr.ds1.Width), Height: int(mr.ds1.Height)}
|
||||||
@ -132,7 +82,7 @@ func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity
|
|||||||
if monstat != nil {
|
if monstat != nil {
|
||||||
// Temorary use of Lookup.
|
// Temorary use of Lookup.
|
||||||
npcX, npcY := (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
|
npcX, npcY := (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
|
||||||
npc, err := d2mapentity.NewNPC(npcX, npcY, monstat, 0)
|
npc, err := mr.entity.NewNPC(npcX, npcY, monstat, 0)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
npc.SetPaths(convertPaths(tileOffsetX, tileOffsetY, object.Paths))
|
npc.SetPaths(convertPaths(tileOffsetX, tileOffsetY, object.Paths))
|
||||||
@ -153,7 +103,7 @@ func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity
|
|||||||
objectRecord := d2datadict.Objects[lookup.ObjectsTxtId]
|
objectRecord := d2datadict.Objects[lookup.ObjectsTxtId]
|
||||||
|
|
||||||
if objectRecord != nil {
|
if objectRecord != nil {
|
||||||
entity, err := d2object.CreateObject((tileOffsetX*5)+object.X,
|
entity, err := mr.entity.NewObject((tileOffsetX*5)+object.X,
|
||||||
(tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits)
|
(tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -173,8 +123,8 @@ func convertPaths(tileOffsetX, tileOffsetY int, paths []d2path.Path) []d2path.Pa
|
|||||||
for i := 0; i < len(paths); i++ {
|
for i := 0; i < len(paths); i++ {
|
||||||
result[i].Action = paths[i].Action
|
result[i].Action = paths[i].Action
|
||||||
result[i].Position = d2vector.NewPosition(
|
result[i].Position = d2vector.NewPosition(
|
||||||
paths[i].Position.X()+float64(tileOffsetX*5),
|
paths[i].Position.X()+float64(tileOffsetX*subtilesPerTile),
|
||||||
paths[i].Position.Y()+float64(tileOffsetY*5))
|
paths[i].Position.Y()+float64(tileOffsetY*subtilesPerTile))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -192,7 +191,7 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
|||||||
lbl.Color[0] = d2util.Color(greyAlpha100)
|
lbl.Color[0] = d2util.Color(greyAlpha100)
|
||||||
lbl.Alignment = d2gui.HorizontalAlignCenter
|
lbl.Alignment = d2gui.HorizontalAlignCenter
|
||||||
|
|
||||||
animation, _ := d2asset.LoadAnimation(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
animation, _ := ui.asset.LoadAnimation(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||||
buttonSprite, _ := ui.NewSprite(animation)
|
buttonSprite, _ := ui.NewSprite(animation)
|
||||||
|
|
||||||
for i := 0; i < buttonLayout.XSegments; i++ {
|
for i := 0; i < buttonLayout.XSegments; i++ {
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Checkbox represents a checkbox UI element
|
// Checkbox represents a checkbox UI element
|
||||||
@ -32,7 +31,7 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.Checkbox, d2resource.PaletteFechar)
|
animation, _ := ui.asset.LoadAnimation(d2resource.Checkbox, d2resource.PaletteFechar)
|
||||||
checkboxSprite, _ := ui.NewSprite(animation)
|
checkboxSprite, _ := ui.NewSprite(animation)
|
||||||
result.width, result.height, _ = checkboxSprite.GetFrameSize(0)
|
result.width, result.height, _ = checkboxSprite.GetFrameSize(0)
|
||||||
checkboxSprite.SetPosition(0, 0)
|
checkboxSprite.SetPosition(0, 0)
|
||||||
|
@ -2,6 +2,7 @@ package d2ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CursorButton represents a mouse button
|
// CursorButton represents a mouse button
|
||||||
@ -16,11 +17,13 @@ const (
|
|||||||
|
|
||||||
// NewUIManager creates a UIManager instance with the given input and audio provider
|
// NewUIManager creates a UIManager instance with the given input and audio provider
|
||||||
func NewUIManager(
|
func NewUIManager(
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
input d2interface.InputManager,
|
input d2interface.InputManager,
|
||||||
audio d2interface.AudioProvider,
|
audio d2interface.AudioProvider,
|
||||||
) *UIManager {
|
) *UIManager {
|
||||||
ui := &UIManager{
|
ui := &UIManager{
|
||||||
|
asset: asset,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
inputManager: input,
|
inputManager: input,
|
||||||
audio: audio,
|
audio: audio,
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ type Label struct {
|
|||||||
|
|
||||||
// NewLabel creates a new instance of a UI label
|
// NewLabel creates a new instance of a UI label
|
||||||
func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label {
|
func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label {
|
||||||
font, _ := d2asset.LoadFont(fontPath+".tbl", fontPath+".dc6", palettePath)
|
font, _ := ui.asset.LoadFont(fontPath+".tbl", fontPath+".dc6", palettePath)
|
||||||
result := &Label{
|
result := &Label{
|
||||||
Alignment: d2gui.HorizontalAlignLeft,
|
Alignment: d2gui.HorizontalAlignLeft,
|
||||||
Color: map[int]color.Color{0: color.White},
|
Color: map[int]color.Color{0: color.White},
|
||||||
|
@ -3,7 +3,6 @@ package d2ui
|
|||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -29,7 +28,7 @@ type Scrollbar struct {
|
|||||||
|
|
||||||
// NewScrollbar creates a scrollbar instance
|
// NewScrollbar creates a scrollbar instance
|
||||||
func (ui *UIManager) NewScrollbar(x, y, height int) *Scrollbar {
|
func (ui *UIManager) NewScrollbar(x, y, height int) *Scrollbar {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.Scrollbar, d2resource.PaletteSky)
|
animation, _ := ui.asset.LoadAnimation(d2resource.Scrollbar, d2resource.PaletteSky)
|
||||||
scrollbarSprite, _ := ui.NewSprite(animation)
|
scrollbarSprite, _ := ui.NewSprite(animation)
|
||||||
result := &Scrollbar{
|
result := &Scrollbar{
|
||||||
visible: true,
|
visible: true,
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TextBox represents a text input box
|
// TextBox represents a text input box
|
||||||
@ -27,7 +26,7 @@ type TextBox struct {
|
|||||||
|
|
||||||
// NewTextbox creates a new instance of a text box
|
// NewTextbox creates a new instance of a text box
|
||||||
func (ui *UIManager) NewTextbox() *TextBox {
|
func (ui *UIManager) NewTextbox() *TextBox {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
animation, _ := ui.asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
||||||
bgSprite, _ := ui.NewSprite(animation)
|
bgSprite, _ := ui.NewSprite(animation)
|
||||||
tb := &TextBox{
|
tb := &TextBox{
|
||||||
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
@ -3,6 +3,8 @@ package d2ui
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
@ -10,6 +12,7 @@ import (
|
|||||||
|
|
||||||
// UIManager manages a collection of UI elements (buttons, textboxes, labels)
|
// UIManager manages a collection of UI elements (buttons, textboxes, labels)
|
||||||
type UIManager struct {
|
type UIManager struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
inputManager d2interface.InputManager
|
inputManager d2interface.InputManager
|
||||||
audio d2interface.AudioProvider
|
audio d2interface.AudioProvider
|
||||||
|
@ -8,17 +8,20 @@ import (
|
|||||||
|
|
||||||
// BlizzardIntro represents the Blizzard Intro screen
|
// BlizzardIntro represents the Blizzard Intro screen
|
||||||
type BlizzardIntro struct {
|
type BlizzardIntro struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
videoDecoder *d2video.BinkDecoder
|
videoDecoder *d2video.BinkDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateBlizzardIntro creates a Blizzard Intro screen
|
// CreateBlizzardIntro creates a Blizzard Intro screen
|
||||||
func CreateBlizzardIntro() *BlizzardIntro {
|
func CreateBlizzardIntro(asset *d2asset.AssetManager) *BlizzardIntro {
|
||||||
return &BlizzardIntro{}
|
return &BlizzardIntro{
|
||||||
|
asset: asset,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnLoad loads the resources for the Blizzard Intro screen
|
// OnLoad loads the resources for the Blizzard Intro screen
|
||||||
func (v *BlizzardIntro) OnLoad(loading d2screen.LoadingState) {
|
func (v *BlizzardIntro) OnLoad(loading d2screen.LoadingState) {
|
||||||
videoBytes, err := d2asset.LoadFile("/data/local/video/BlizNorth640x480.bik")
|
videoBytes, err := v.asset.LoadFile("/data/local/video/BlizNorth640x480.bik")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loading.Error(err)
|
loading.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
|
|
||||||
// CharacterSelect represents the character select screen
|
// CharacterSelect represents the character select screen
|
||||||
type CharacterSelect struct {
|
type CharacterSelect struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
|
*d2mapentity.MapEntityFactory
|
||||||
background *d2ui.Sprite
|
background *d2ui.Sprite
|
||||||
newCharButton *d2ui.Button
|
newCharButton *d2ui.Button
|
||||||
convertCharButton *d2ui.Button
|
convertCharButton *d2ui.Button
|
||||||
@ -54,6 +56,7 @@ type CharacterSelect struct {
|
|||||||
// CreateCharacterSelect creates the character select screen and returns a pointer to it
|
// CreateCharacterSelect creates the character select screen and returns a pointer to it
|
||||||
func CreateCharacterSelect(
|
func CreateCharacterSelect(
|
||||||
navigator Navigator,
|
navigator Navigator,
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
@ -63,6 +66,8 @@ func CreateCharacterSelect(
|
|||||||
) *CharacterSelect {
|
) *CharacterSelect {
|
||||||
return &CharacterSelect{
|
return &CharacterSelect{
|
||||||
selectedCharacter: -1,
|
selectedCharacter: -1,
|
||||||
|
asset: asset,
|
||||||
|
MapEntityFactory: d2mapentity.NewMapEntityFactory(asset),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
connectionType: connectionType,
|
connectionType: connectionType,
|
||||||
connectionHost: connectionHost,
|
connectionHost: connectionHost,
|
||||||
@ -133,7 +138,8 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
|
|||||||
|
|
||||||
loading.Progress(tenPercent)
|
loading.Progress(tenPercent)
|
||||||
|
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
|
animation, _ := v.asset.LoadAnimation(d2resource.CharacterSelectionBackground,
|
||||||
|
d2resource.PaletteSky)
|
||||||
bgX, bgY := 0, 0
|
bgX, bgY := 0, 0
|
||||||
v.background, _ = v.uiManager.NewSprite(animation)
|
v.background, _ = v.uiManager.NewSprite(animation)
|
||||||
v.background.SetPosition(bgX, bgY)
|
v.background.SetPosition(bgX, bgY)
|
||||||
@ -154,12 +160,13 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
|
|||||||
deleteConfirmX, deleteConfirmY := 400, 185
|
deleteConfirmX, deleteConfirmY := 400, 185
|
||||||
v.deleteCharConfirmLabel.SetPosition(deleteConfirmX, deleteConfirmY)
|
v.deleteCharConfirmLabel.SetPosition(deleteConfirmX, deleteConfirmY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
|
animation, _ = v.asset.LoadAnimation(d2resource.CharacterSelectionSelectBox,
|
||||||
|
d2resource.PaletteSky)
|
||||||
v.selectionBox, _ = v.uiManager.NewSprite(animation)
|
v.selectionBox, _ = v.uiManager.NewSprite(animation)
|
||||||
selBoxX, selBoxY := 37, 86
|
selBoxX, selBoxY := 37, 86
|
||||||
v.selectionBox.SetPosition(selBoxX, selBoxY)
|
v.selectionBox.SetPosition(selBoxX, selBoxY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
animation, _ = v.asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||||
v.okCancelBox, _ = v.uiManager.NewSprite(animation)
|
v.okCancelBox, _ = v.uiManager.NewSprite(animation)
|
||||||
okCancelX, okCancelY := 270, 175
|
okCancelX, okCancelY := 270, 175
|
||||||
v.okCancelBox.SetPosition(okCancelX, okCancelY)
|
v.okCancelBox.SetPosition(okCancelX, okCancelY)
|
||||||
@ -283,7 +290,7 @@ func (v *CharacterSelect) updateCharacterBoxes() {
|
|||||||
equipment := d2inventory.HeroObjects[heroType]
|
equipment := d2inventory.HeroObjects[heroType]
|
||||||
|
|
||||||
// TODO: Generate or load the object from the actual player data...
|
// TODO: Generate or load the object from the actual player data...
|
||||||
v.characterImage[i] = d2mapentity.NewPlayer("", "", 0, 0, 0,
|
v.characterImage[i] = v.NewPlayer("", "", 0, 0, 0,
|
||||||
v.gameStates[idx].HeroType,
|
v.gameStates[idx].HeroType,
|
||||||
v.gameStates[idx].Stats,
|
v.gameStates[idx].Stats,
|
||||||
&equipment,
|
&equipment,
|
||||||
|
@ -39,14 +39,17 @@ type Credits struct {
|
|||||||
cyclesTillNextLine int
|
cyclesTillNextLine int
|
||||||
doneWithCredits bool
|
doneWithCredits bool
|
||||||
|
|
||||||
|
asset *d2asset.AssetManager
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
navigator Navigator
|
navigator Navigator
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCredits creates an instance of the credits screen
|
// CreateCredits creates an instance of the credits screen
|
||||||
func CreateCredits(navigator Navigator, renderer d2interface.Renderer, ui *d2ui.UIManager) *Credits {
|
func CreateCredits(navigator Navigator, asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||||
|
ui *d2ui.UIManager) *Credits {
|
||||||
result := &Credits{
|
result := &Credits{
|
||||||
|
asset: asset,
|
||||||
labels: make([]*labelItem, 0),
|
labels: make([]*labelItem, 0),
|
||||||
cycleTime: 0,
|
cycleTime: 0,
|
||||||
doneWithCredits: false,
|
doneWithCredits: false,
|
||||||
@ -86,7 +89,7 @@ func (v *Credits) LoadContributors() []string {
|
|||||||
|
|
||||||
// OnLoad is called to load the resources for the credits screen
|
// OnLoad is called to load the resources for the credits screen
|
||||||
func (v *Credits) OnLoad(loading d2screen.LoadingState) {
|
func (v *Credits) OnLoad(loading d2screen.LoadingState) {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky)
|
animation, _ := v.asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky)
|
||||||
v.creditsBackground, _ = v.uiManager.NewSprite(animation)
|
v.creditsBackground, _ = v.uiManager.NewSprite(animation)
|
||||||
v.creditsBackground.SetPosition(creditsX, creditsY)
|
v.creditsBackground.SetPosition(creditsX, creditsY)
|
||||||
loading.Progress(twentyPercent)
|
loading.Progress(twentyPercent)
|
||||||
@ -96,7 +99,7 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
|
|||||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||||
loading.Progress(fourtyPercent)
|
loading.Progress(fourtyPercent)
|
||||||
|
|
||||||
fileData, err := d2asset.LoadFile(d2resource.CreditsText)
|
fileData, err := v.asset.LoadFile(d2resource.CreditsText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loading.Error(err)
|
loading.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||||
|
|
||||||
@ -30,6 +32,8 @@ const (
|
|||||||
|
|
||||||
// Game represents the Gameplay screen
|
// Game represents the Gameplay screen
|
||||||
type Game struct {
|
type Game struct {
|
||||||
|
*d2mapentity.MapEntityFactory
|
||||||
|
asset *d2asset.AssetManager
|
||||||
gameClient *d2client.GameClient
|
gameClient *d2client.GameClient
|
||||||
mapRenderer *d2maprenderer.MapRenderer
|
mapRenderer *d2maprenderer.MapRenderer
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
@ -50,6 +54,8 @@ type Game struct {
|
|||||||
// CreateGame creates the Gameplay screen and returns a pointer to it
|
// CreateGame creates the Gameplay screen and returns a pointer to it
|
||||||
func CreateGame(
|
func CreateGame(
|
||||||
navigator Navigator,
|
navigator Navigator,
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
|
ui *d2ui.UIManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
@ -71,19 +77,21 @@ func CreateGame(
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &Game{
|
result := &Game{
|
||||||
|
asset: asset,
|
||||||
gameClient: gameClient,
|
gameClient: gameClient,
|
||||||
gameControls: nil,
|
gameControls: nil,
|
||||||
localPlayer: nil,
|
localPlayer: nil,
|
||||||
lastRegionType: d2enum.RegionNone,
|
lastRegionType: d2enum.RegionNone,
|
||||||
ticksSinceLevelCheck: 0,
|
ticksSinceLevelCheck: 0,
|
||||||
mapRenderer: d2maprenderer.CreateMapRenderer(renderer, gameClient.MapEngine, term, startX, startY),
|
mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer,
|
||||||
escapeMenu: NewEscapeMenu(navigator, renderer, audioProvider),
|
gameClient.MapEngine, term, startX, startY),
|
||||||
inputManager: inputManager,
|
escapeMenu: NewEscapeMenu(navigator, renderer, audioProvider),
|
||||||
audioProvider: audioProvider,
|
inputManager: inputManager,
|
||||||
renderer: renderer,
|
audioProvider: audioProvider,
|
||||||
terminal: term,
|
renderer: renderer,
|
||||||
soundEngine: d2audio.NewSoundEngine(audioProvider, term),
|
terminal: term,
|
||||||
uiManager: d2ui.NewUIManager(renderer, inputManager, audioProvider),
|
soundEngine: d2audio.NewSoundEngine(audioProvider, term),
|
||||||
|
uiManager: ui,
|
||||||
}
|
}
|
||||||
result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine)
|
result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine)
|
||||||
|
|
||||||
@ -135,12 +143,13 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
|
|||||||
v.terminal.OutputErrorf("no monstat entry for \"%s\"", name)
|
v.terminal.OutputErrorf("no monstat entry for \"%s\"", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var monster *d2mapentity.NPC
|
|
||||||
monster, err = d2mapentity.NewNPC(x, y, monstat, 0)
|
monster, err := v.gameClient.MapEngine.NewNPC(x, y, monstat, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.terminal.OutputErrorf("error generating monster \"%s\": %v", name, err)
|
v.terminal.OutputErrorf("error generating monster \"%s\": %v", name, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v.gameClient.MapEngine.AddEntity(monster)
|
v.gameClient.MapEngine.AddEntity(monster)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -266,7 +275,7 @@ func (v *Game) bindGameControls() error {
|
|||||||
v.localPlayer = player
|
v.localPlayer = player
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
v.gameControls, err = d2player.NewGameControls(v.renderer, player,
|
v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player,
|
||||||
v.gameClient.MapEngine, v.mapRenderer, v, v.terminal, v.uiManager, v.gameClient.IsSinglePlayer())
|
v.gameClient.MapEngine, v.mapRenderer, v, v.terminal, v.uiManager, v.gameClient.IsSinglePlayer())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -111,6 +111,7 @@ type MainMenu struct {
|
|||||||
screenMode mainMenuScreenMode
|
screenMode mainMenuScreenMode
|
||||||
leftButtonHeld bool
|
leftButtonHeld bool
|
||||||
|
|
||||||
|
asset *d2asset.AssetManager
|
||||||
inputManager d2interface.InputManager
|
inputManager d2interface.InputManager
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
audioProvider d2interface.AudioProvider
|
audioProvider d2interface.AudioProvider
|
||||||
@ -124,6 +125,7 @@ type MainMenu struct {
|
|||||||
// CreateMainMenu creates an instance of MainMenu
|
// CreateMainMenu creates an instance of MainMenu
|
||||||
func CreateMainMenu(
|
func CreateMainMenu(
|
||||||
navigator Navigator,
|
navigator Navigator,
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
@ -131,6 +133,7 @@ func CreateMainMenu(
|
|||||||
buildInfo BuildInfo,
|
buildInfo BuildInfo,
|
||||||
) *MainMenu {
|
) *MainMenu {
|
||||||
return &MainMenu{
|
return &MainMenu{
|
||||||
|
asset: asset,
|
||||||
screenMode: ScreenModeUnknown,
|
screenMode: ScreenModeUnknown,
|
||||||
leftButtonHeld: true,
|
leftButtonHeld: true,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
@ -169,19 +172,19 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *MainMenu) loadBackgroundSprites() {
|
func (v *MainMenu) loadBackgroundSprites() {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
|
animation, _ := v.asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
|
||||||
v.background, _ = v.uiManager.NewSprite(animation)
|
v.background, _ = v.uiManager.NewSprite(animation)
|
||||||
v.background.SetPosition(backgroundX, backgroundY)
|
v.background.SetPosition(backgroundX, backgroundY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
|
animation, _ = v.asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
|
||||||
v.trademarkBackground, _ = v.uiManager.NewSprite(animation)
|
v.trademarkBackground, _ = v.uiManager.NewSprite(animation)
|
||||||
v.trademarkBackground.SetPosition(backgroundX, backgroundY)
|
v.trademarkBackground.SetPosition(backgroundX, backgroundY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
|
animation, _ = v.asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
|
||||||
v.tcpIPBackground, _ = v.uiManager.NewSprite(animation)
|
v.tcpIPBackground, _ = v.uiManager.NewSprite(animation)
|
||||||
v.tcpIPBackground.SetPosition(backgroundX, backgroundY)
|
v.tcpIPBackground.SetPosition(backgroundX, backgroundY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
animation, _ = v.asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||||
v.serverIPBackground, _ = v.uiManager.NewSprite(animation)
|
v.serverIPBackground, _ = v.uiManager.NewSprite(animation)
|
||||||
v.serverIPBackground.SetPosition(serverIPbackgroundX, serverIPbackgroundY)
|
v.serverIPBackground.SetPosition(serverIPbackgroundX, serverIPbackgroundY)
|
||||||
}
|
}
|
||||||
@ -233,24 +236,24 @@ func (v *MainMenu) createLabels(loading d2screen.LoadingState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
|
func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
|
animation, _ := v.asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
|
||||||
v.diabloLogoLeft, _ = v.uiManager.NewSprite(animation)
|
v.diabloLogoLeft, _ = v.uiManager.NewSprite(animation)
|
||||||
v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate)
|
v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate)
|
||||||
v.diabloLogoLeft.PlayForward()
|
v.diabloLogoLeft.PlayForward()
|
||||||
v.diabloLogoLeft.SetPosition(diabloLogoX, diabloLogoY)
|
v.diabloLogoLeft.SetPosition(diabloLogoX, diabloLogoY)
|
||||||
loading.Progress(sixtyPercent)
|
loading.Progress(sixtyPercent)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
|
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
|
||||||
v.diabloLogoRight, _ = v.uiManager.NewSprite(animation)
|
v.diabloLogoRight, _ = v.uiManager.NewSprite(animation)
|
||||||
v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate)
|
v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate)
|
||||||
v.diabloLogoRight.PlayForward()
|
v.diabloLogoRight.PlayForward()
|
||||||
v.diabloLogoRight.SetPosition(diabloLogoX, diabloLogoY)
|
v.diabloLogoRight.SetPosition(diabloLogoX, diabloLogoY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
|
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
|
||||||
v.diabloLogoLeftBack, _ = v.uiManager.NewSprite(animation)
|
v.diabloLogoLeftBack, _ = v.uiManager.NewSprite(animation)
|
||||||
v.diabloLogoLeftBack.SetPosition(diabloLogoX, diabloLogoY)
|
v.diabloLogoLeftBack.SetPosition(diabloLogoX, diabloLogoY)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
|
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
|
||||||
v.diabloLogoRightBack, _ = v.uiManager.NewSprite(animation)
|
v.diabloLogoRightBack, _ = v.uiManager.NewSprite(animation)
|
||||||
v.diabloLogoRightBack.SetPosition(diabloLogoX, diabloLogoY)
|
v.diabloLogoRightBack.SetPosition(diabloLogoX, diabloLogoY)
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||||
)
|
)
|
||||||
@ -87,6 +84,7 @@ func getRegions() []regionSpec {
|
|||||||
|
|
||||||
// MapEngineTest represents the MapEngineTest screen
|
// MapEngineTest represents the MapEngineTest screen
|
||||||
type MapEngineTest struct {
|
type MapEngineTest struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
gameState *d2player.PlayerState
|
gameState *d2player.PlayerState
|
||||||
mapEngine *d2mapengine.MapEngine
|
mapEngine *d2mapengine.MapEngine
|
||||||
mapRenderer *d2maprenderer.MapRenderer
|
mapRenderer *d2maprenderer.MapRenderer
|
||||||
@ -112,6 +110,7 @@ type MapEngineTest struct {
|
|||||||
// CreateMapEngineTest creates the Map Engine Test screen and returns a pointer to it
|
// CreateMapEngineTest creates the Map Engine Test screen and returns a pointer to it
|
||||||
func CreateMapEngineTest(currentRegion,
|
func CreateMapEngineTest(currentRegion,
|
||||||
levelPreset int,
|
levelPreset int,
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
term d2interface.Terminal,
|
term d2interface.Terminal,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
@ -124,6 +123,7 @@ func CreateMapEngineTest(currentRegion,
|
|||||||
fileIndex: 0,
|
fileIndex: 0,
|
||||||
regionSpec: regionSpec{},
|
regionSpec: regionSpec{},
|
||||||
filesCount: 0,
|
filesCount: 0,
|
||||||
|
asset: asset,
|
||||||
terminal: term,
|
terminal: term,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
inputManager: inputManager,
|
inputManager: inputManager,
|
||||||
@ -171,7 +171,7 @@ func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) {
|
|||||||
met.mapEngine.SetSeed(time.Now().UnixNano())
|
met.mapEngine.SetSeed(time.Now().UnixNano())
|
||||||
d2mapgen.GenerateAct1Overworld(met.mapEngine)
|
d2mapgen.GenerateAct1Overworld(met.mapEngine)
|
||||||
} else {
|
} else {
|
||||||
met.mapEngine = d2mapengine.CreateMapEngine() // necessary for map name update
|
met.mapEngine = d2mapengine.CreateMapEngine(met.asset) // necessary for map name update
|
||||||
met.mapEngine.SetSeed(time.Now().UnixNano())
|
met.mapEngine.SetSeed(time.Now().UnixNano())
|
||||||
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
|
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
|
||||||
}
|
}
|
||||||
@ -193,11 +193,12 @@ func (met *MapEngineTest) OnLoad(loading d2screen.LoadingState) {
|
|||||||
|
|
||||||
loading.Progress(twentyPercent)
|
loading.Progress(twentyPercent)
|
||||||
|
|
||||||
met.mapEngine = d2mapengine.CreateMapEngine()
|
met.mapEngine = d2mapengine.CreateMapEngine(met.asset)
|
||||||
|
|
||||||
loading.Progress(fiftyPercent)
|
loading.Progress(fiftyPercent)
|
||||||
|
|
||||||
met.mapRenderer = d2maprenderer.CreateMapRenderer(met.renderer, met.mapEngine, met.terminal, 0.0, 0.0)
|
met.mapRenderer = d2maprenderer.CreateMapRenderer(met.asset, met.renderer, met.mapEngine,
|
||||||
|
met.terminal, 0.0, 0.0)
|
||||||
|
|
||||||
loading.Progress(seventyPercent)
|
loading.Progress(seventyPercent)
|
||||||
met.loadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
|
met.loadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
|
||||||
|
@ -4,13 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
||||||
@ -269,6 +268,7 @@ func (hri *HeroRenderInfo) advance(elapsed float64) {
|
|||||||
|
|
||||||
// SelectHeroClass represents the Select Hero Class screen
|
// SelectHeroClass represents the Select Hero Class screen
|
||||||
type SelectHeroClass struct {
|
type SelectHeroClass struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
bgImage *d2ui.Sprite
|
bgImage *d2ui.Sprite
|
||||||
campfire *d2ui.Sprite
|
campfire *d2ui.Sprite
|
||||||
@ -298,6 +298,7 @@ type SelectHeroClass struct {
|
|||||||
// CreateSelectHeroClass creates an instance of a SelectHeroClass
|
// CreateSelectHeroClass creates an instance of a SelectHeroClass
|
||||||
func CreateSelectHeroClass(
|
func CreateSelectHeroClass(
|
||||||
navigator Navigator,
|
navigator Navigator,
|
||||||
|
manager *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
ui *d2ui.UIManager,
|
ui *d2ui.UIManager,
|
||||||
@ -732,7 +733,7 @@ func (v *SelectHeroClass) loadSprite(animationPath string, position image.Point,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
animation, err := d2asset.LoadAnimation(animationPath, d2resource.PaletteFechar)
|
animation, err := v.asset.LoadAnimation(animationPath, d2resource.PaletteFechar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("could not load animation: %s\n", animationPath)
|
fmt.Printf("could not load animation: %s\n", animationPath)
|
||||||
return nil
|
return nil
|
||||||
|
@ -47,6 +47,7 @@ const (
|
|||||||
// 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
|
actionableRegions []ActionableRegion
|
||||||
|
asset *d2asset.AssetManager
|
||||||
renderer d2interface.Renderer // TODO: This shouldn't be a dependency
|
renderer d2interface.Renderer // TODO: This shouldn't be a dependency
|
||||||
inputListener InputCallbackListener
|
inputListener InputCallbackListener
|
||||||
hero *d2mapentity.Player
|
hero *d2mapentity.Player
|
||||||
@ -103,6 +104,7 @@ const (
|
|||||||
|
|
||||||
// NewGameControls creates a GameControls instance and returns a pointer to it
|
// NewGameControls creates a GameControls instance and returns a pointer to it
|
||||||
func NewGameControls(
|
func NewGameControls(
|
||||||
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
hero *d2mapentity.Player,
|
hero *d2mapentity.Player,
|
||||||
mapEngine *d2mapengine.MapEngine,
|
mapEngine *d2mapengine.MapEngine,
|
||||||
@ -161,16 +163,17 @@ func NewGameControls(
|
|||||||
globeStatsLabel := hpManaStatsLabel
|
globeStatsLabel := hpManaStatsLabel
|
||||||
|
|
||||||
gc := &GameControls{
|
gc := &GameControls{
|
||||||
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
hero: hero,
|
hero: hero,
|
||||||
mapEngine: mapEngine,
|
mapEngine: mapEngine,
|
||||||
inputListener: inputListener,
|
inputListener: inputListener,
|
||||||
mapRenderer: mapRenderer,
|
mapRenderer: mapRenderer,
|
||||||
inventory: NewInventory(ui, inventoryRecord),
|
inventory: NewInventory(asset, ui, inventoryRecord),
|
||||||
heroStatsPanel: NewHeroStatsPanel(ui, hero.Name(), hero.Class, hero.Stats),
|
heroStatsPanel: NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats),
|
||||||
helpOverlay: help.NewHelpOverlay(renderer),
|
helpOverlay: help.NewHelpOverlay(asset, renderer, ui),
|
||||||
miniPanel: newMiniPanel(ui, isSinglePlayer),
|
miniPanel: newMiniPanel(asset, ui, isSinglePlayer),
|
||||||
missileID: missileID,
|
missileID: missileID,
|
||||||
nameLabel: hoverLabel,
|
nameLabel: hoverLabel,
|
||||||
zoneChangeText: zoneLabel,
|
zoneChangeText: zoneLabel,
|
||||||
@ -378,20 +381,20 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
|||||||
|
|
||||||
// Load loads the resources required for the GameControls
|
// Load loads the resources required for the GameControls
|
||||||
func (g *GameControls) Load() {
|
func (g *GameControls) Load() {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
animation, _ := g.asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
||||||
g.globeSprite, _ = g.uiManager.NewSprite(animation)
|
g.globeSprite, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
animation, _ = g.asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
||||||
g.hpManaStatusSprite, _ = g.uiManager.NewSprite(animation)
|
g.hpManaStatusSprite, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
animation, _ = g.asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
||||||
g.mainPanel, _ = g.uiManager.NewSprite(animation)
|
g.mainPanel, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.MenuButton, d2resource.PaletteSky)
|
animation, _ = g.asset.LoadAnimation(d2resource.MenuButton, d2resource.PaletteSky)
|
||||||
_ = animation.SetCurrentFrame(2)
|
_ = animation.SetCurrentFrame(2)
|
||||||
g.menuButton, _ = g.uiManager.NewSprite(animation)
|
g.menuButton, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.GenericSkills, d2resource.PaletteSky)
|
animation, _ = g.asset.LoadAnimation(d2resource.GenericSkills, d2resource.PaletteSky)
|
||||||
g.skillIcon, _ = g.uiManager.NewSprite(animation)
|
g.skillIcon, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
g.loadUIButtons()
|
g.loadUIButtons()
|
||||||
|
@ -2,9 +2,10 @@ package help
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
@ -25,6 +26,7 @@ const (
|
|||||||
|
|
||||||
// HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed
|
// HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed
|
||||||
type Overlay struct {
|
type Overlay struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
isOpen bool
|
isOpen bool
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
frames []*d2ui.Sprite
|
frames []*d2ui.Sprite
|
||||||
@ -36,9 +38,12 @@ type Overlay struct {
|
|||||||
layout *d2gui.Layout
|
layout *d2gui.Layout
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHelpOverlay(renderer d2interface.Renderer) *Overlay {
|
func NewHelpOverlay(asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||||
|
ui *d2ui.UIManager) *Overlay {
|
||||||
h := &Overlay{
|
h := &Overlay{
|
||||||
renderer: renderer,
|
asset: asset,
|
||||||
|
renderer: renderer,
|
||||||
|
uiManager: ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
return h
|
return h
|
||||||
@ -89,7 +94,7 @@ func (h *Overlay) Load() {
|
|||||||
prevY = 0
|
prevY = 0
|
||||||
)
|
)
|
||||||
for frameIndex := 0; frameIndex < 7; frameIndex++ {
|
for frameIndex := 0; frameIndex < 7; frameIndex++ {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.HelpBorder, d2resource.PaletteSky)
|
animation, _ := h.asset.LoadAnimation(d2resource.HelpBorder, d2resource.PaletteSky)
|
||||||
_ = animation.SetCurrentFrame(frameIndex)
|
_ = animation.SetCurrentFrame(frameIndex)
|
||||||
f, _ := h.uiManager.NewSprite(animation)
|
f, _ := h.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
@ -139,7 +144,7 @@ func (h *Overlay) Load() {
|
|||||||
|
|
||||||
// Close
|
// Close
|
||||||
|
|
||||||
anim, _ := d2asset.LoadAnimation(d2resource.SquareButton, d2resource.PaletteSky)
|
anim, _ := h.asset.LoadAnimation(d2resource.SquareButton, d2resource.PaletteSky)
|
||||||
close, _ := h.uiManager.NewSprite(anim)
|
close, _ := h.uiManager.NewSprite(anim)
|
||||||
_ = close.SetCurrentFrame(0)
|
_ = close.SetCurrentFrame(0)
|
||||||
close.SetPosition(685, 57)
|
close.SetPosition(685, 57)
|
||||||
@ -339,7 +344,7 @@ func (h *Overlay) createBullet(c callout) {
|
|||||||
newLabel.SetPosition(c.LabelX, c.LabelY)
|
newLabel.SetPosition(c.LabelX, c.LabelY)
|
||||||
h.text = append(h.text, newLabel)
|
h.text = append(h.text, newLabel)
|
||||||
|
|
||||||
anim, _ := d2asset.LoadAnimation(d2resource.HelpYellowBullet, d2resource.PaletteSky)
|
anim, _ := h.asset.LoadAnimation(d2resource.HelpYellowBullet, d2resource.PaletteSky)
|
||||||
newDot, _ := h.uiManager.NewSprite(anim)
|
newDot, _ := h.uiManager.NewSprite(anim)
|
||||||
_ = newDot.SetCurrentFrame(0)
|
_ = newDot.SetCurrentFrame(0)
|
||||||
newDot.SetPosition(c.DotX, c.DotY+14)
|
newDot.SetPosition(c.DotX, c.DotY+14)
|
||||||
@ -365,7 +370,7 @@ func (h *Overlay) createCallout(c callout) {
|
|||||||
}
|
}
|
||||||
h.lines = append(h.lines, l)
|
h.lines = append(h.lines, l)
|
||||||
|
|
||||||
anim, _ := d2asset.LoadAnimation(d2resource.HelpWhiteBullet, d2resource.PaletteSky)
|
anim, _ := h.asset.LoadAnimation(d2resource.HelpWhiteBullet, d2resource.PaletteSky)
|
||||||
newDot, _ := h.uiManager.NewSprite(anim)
|
newDot, _ := h.uiManager.NewSprite(anim)
|
||||||
_ = newDot.SetCurrentFrame(0)
|
_ = newDot.SetCurrentFrame(0)
|
||||||
newDot.SetPosition(c.DotX, c.DotY)
|
newDot.SetPosition(c.DotX, c.DotY)
|
||||||
|
@ -41,6 +41,7 @@ type StatsPanelLabels struct {
|
|||||||
|
|
||||||
// HeroStatsPanel represents the hero status panel
|
// HeroStatsPanel represents the hero status panel
|
||||||
type HeroStatsPanel struct {
|
type HeroStatsPanel struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
frame *d2ui.Sprite
|
frame *d2ui.Sprite
|
||||||
panel *d2ui.Sprite
|
panel *d2ui.Sprite
|
||||||
@ -57,12 +58,13 @@ type HeroStatsPanel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewHeroStatsPanel creates a new hero status panel
|
// NewHeroStatsPanel creates a new hero status panel
|
||||||
func NewHeroStatsPanel(ui *d2ui.UIManager, heroName string, heroClass d2enum.Hero,
|
func NewHeroStatsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName string, heroClass d2enum.Hero,
|
||||||
heroState *d2hero.HeroStatsState) *HeroStatsPanel {
|
heroState *d2hero.HeroStatsState) *HeroStatsPanel {
|
||||||
originX := 0
|
originX := 0
|
||||||
originY := 0
|
originY := 0
|
||||||
|
|
||||||
return &HeroStatsPanel{
|
return &HeroStatsPanel{
|
||||||
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
renderer: ui.Renderer(),
|
renderer: ui.Renderer(),
|
||||||
originX: originX,
|
originX: originX,
|
||||||
@ -76,9 +78,9 @@ func NewHeroStatsPanel(ui *d2ui.UIManager, heroName string, heroClass d2enum.Her
|
|||||||
|
|
||||||
// Load loads the data for the hero status panel
|
// Load loads the data for the hero status panel
|
||||||
func (s *HeroStatsPanel) Load() {
|
func (s *HeroStatsPanel) Load() {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
animation, _ := s.asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||||
s.frame, _ = s.uiManager.NewSprite(animation)
|
s.frame, _ = s.uiManager.NewSprite(animation)
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
animation, _ = s.asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||||
s.panel, _ = s.uiManager.NewSprite(animation)
|
s.panel, _ = s.uiManager.NewSprite(animation)
|
||||||
s.initStatValueLabels()
|
s.initStatValueLabels()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
// Inventory represents the inventory
|
// Inventory represents the inventory
|
||||||
type Inventory struct {
|
type Inventory struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
frame *d2ui.Sprite
|
frame *d2ui.Sprite
|
||||||
panel *d2ui.Sprite
|
panel *d2ui.Sprite
|
||||||
@ -32,13 +33,15 @@ type Inventory struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewInventory creates an inventory instance and returns a pointer to it
|
// NewInventory creates an inventory instance and returns a pointer to it
|
||||||
func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inventory {
|
func NewInventory(asset *d2asset.AssetManager, 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
|
||||||
|
|
||||||
return &Inventory{
|
return &Inventory{
|
||||||
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
grid: NewItemGrid(ui, record),
|
grid: NewItemGrid(asset, ui, record),
|
||||||
originX: record.Panel.Left,
|
originX: record.Panel.Left,
|
||||||
hoverLabel: hoverLabel,
|
hoverLabel: hoverLabel,
|
||||||
// originY: record.Panel.Top,
|
// originY: record.Panel.Top,
|
||||||
@ -68,10 +71,10 @@ func (g *Inventory) Close() {
|
|||||||
|
|
||||||
// Load loads the resources required by the inventory
|
// Load loads the resources required by the inventory
|
||||||
func (g *Inventory) Load() {
|
func (g *Inventory) Load() {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
animation, _ := g.asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||||
g.frame, _ = g.uiManager.NewSprite(animation)
|
g.frame, _ = g.uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
animation, _ = g.asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||||
g.panel, _ = g.uiManager.NewSprite(animation)
|
g.panel, _ = g.uiManager.NewSprite(animation)
|
||||||
items := []InventoryItem{
|
items := []InventoryItem{
|
||||||
diablo2item.NewItem("kit", "Crimson", "of the Bat", "of Frost").Identify(),
|
diablo2item.NewItem("kit", "Crimson", "of the Bat", "of Frost").Identify(),
|
||||||
|
@ -33,6 +33,7 @@ var errorInventoryFull = errors.New("inventory full")
|
|||||||
// ItemGrid is a reusable grid for use with player and merchant inventory.
|
// ItemGrid is a reusable grid for use with player and merchant inventory.
|
||||||
// Handles layout and rendering item icons based on code.
|
// Handles layout and rendering item icons based on code.
|
||||||
type ItemGrid struct {
|
type ItemGrid struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
items []InventoryItem
|
items []InventoryItem
|
||||||
equipmentSlots map[d2enum.EquippedSlot]EquipmentSlot
|
equipmentSlots map[d2enum.EquippedSlot]EquipmentSlot
|
||||||
@ -44,10 +45,12 @@ type ItemGrid struct {
|
|||||||
slotSize int
|
slotSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewItemGrid(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *ItemGrid {
|
func NewItemGrid(asset *d2asset.AssetManager, ui *d2ui.UIManager,
|
||||||
|
record *d2datadict.InventoryRecord) *ItemGrid {
|
||||||
grid := record.Grid
|
grid := record.Grid
|
||||||
|
|
||||||
return &ItemGrid{
|
return &ItemGrid{
|
||||||
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
width: grid.Box.Width,
|
width: grid.Box.Width,
|
||||||
height: grid.Box.Height,
|
height: grid.Box.Height,
|
||||||
@ -118,7 +121,7 @@ func (g *ItemGrid) loadItem(item InventoryItem) {
|
|||||||
var itemSprite *d2ui.Sprite
|
var itemSprite *d2ui.Sprite
|
||||||
|
|
||||||
// TODO: Put the pattern into D2Shared
|
// TODO: Put the pattern into D2Shared
|
||||||
animation, err := d2asset.LoadAnimation(
|
animation, err := g.asset.LoadAnimation(
|
||||||
fmt.Sprintf("/data/global/items/inv%s.dc6", item.GetItemCode()),
|
fmt.Sprintf("/data/global/items/inv%s.dc6", item.GetItemCode()),
|
||||||
d2resource.PaletteSky,
|
d2resource.PaletteSky,
|
||||||
)
|
)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type miniPanel struct {
|
type miniPanel struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
container *d2ui.Sprite
|
container *d2ui.Sprite
|
||||||
button *d2ui.Sprite
|
button *d2ui.Sprite
|
||||||
isOpen bool
|
isOpen bool
|
||||||
@ -16,16 +17,16 @@ type miniPanel struct {
|
|||||||
rectangle d2geom.Rectangle
|
rectangle d2geom.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMiniPanel(uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
func newMiniPanel(asset *d2asset.AssetManager, uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
||||||
miniPanelContainerPath := d2resource.Minipanel
|
miniPanelContainerPath := d2resource.Minipanel
|
||||||
if isSinglePlayer {
|
if isSinglePlayer {
|
||||||
miniPanelContainerPath = d2resource.MinipanelSmall
|
miniPanelContainerPath = d2resource.MinipanelSmall
|
||||||
}
|
}
|
||||||
|
|
||||||
animation, _ := d2asset.LoadAnimation(miniPanelContainerPath, d2resource.PaletteSky)
|
animation, _ := asset.LoadAnimation(miniPanelContainerPath, d2resource.PaletteSky)
|
||||||
containerSprite, _ := uiManager.NewSprite(animation)
|
containerSprite, _ := uiManager.NewSprite(animation)
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.MinipanelButton, d2resource.PaletteSky)
|
animation, _ = asset.LoadAnimation(d2resource.MinipanelButton, d2resource.PaletteSky)
|
||||||
buttonSprite, _ := uiManager.NewSprite(animation)
|
buttonSprite, _ := uiManager.NewSprite(animation)
|
||||||
|
|
||||||
rectangle := d2geom.Rectangle{Left: 325, Top: 526, Width: 156, Height: 26}
|
rectangle := d2geom.Rectangle{Left: 325, Top: 526, Width: 156, Height: 26}
|
||||||
@ -34,7 +35,14 @@ func newMiniPanel(uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
|||||||
rectangle.Width = 182
|
rectangle.Width = 182
|
||||||
}
|
}
|
||||||
|
|
||||||
return &miniPanel{container: containerSprite, button: buttonSprite, isOpen: true, isSinglePlayer: isSinglePlayer, rectangle: rectangle}
|
return &miniPanel{
|
||||||
|
asset: asset,
|
||||||
|
container: containerSprite,
|
||||||
|
button: buttonSprite,
|
||||||
|
isOpen: true,
|
||||||
|
isSinglePlayer: isSinglePlayer,
|
||||||
|
rectangle: rectangle,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *miniPanel) IsOpen() bool {
|
func (m *miniPanel) IsOpen() bool {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package d2localclient
|
package d2localclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
// LocalClientConnection is the implementation of ClientConnection
|
// LocalClientConnection is the implementation of ClientConnection
|
||||||
// for a local client.
|
// for a local client.
|
||||||
type LocalClientConnection struct {
|
type LocalClientConnection struct {
|
||||||
|
asset *d2asset.AssetManager
|
||||||
clientListener d2networking.ClientListener // The game client
|
clientListener d2networking.ClientListener // The game client
|
||||||
uniqueID string // Unique ID generated on construction
|
uniqueID string // Unique ID generated on construction
|
||||||
openNetworkServer bool // True if this is a server
|
openNetworkServer bool // True if this is a server
|
||||||
@ -38,8 +40,9 @@ func (l *LocalClientConnection) SendPacketToClient(packet d2netpacket.NetPacket)
|
|||||||
|
|
||||||
// Create constructs a new LocalClientConnection and returns
|
// Create constructs a new LocalClientConnection and returns
|
||||||
// a pointer to it.
|
// a pointer to it.
|
||||||
func Create(openNetworkServer bool) *LocalClientConnection {
|
func Create(asset *d2asset.AssetManager, openNetworkServer bool) *LocalClientConnection {
|
||||||
result := &LocalClientConnection{
|
result := &LocalClientConnection{
|
||||||
|
asset: asset,
|
||||||
uniqueID: uuid.NewV4().String(),
|
uniqueID: uuid.NewV4().String(),
|
||||||
openNetworkServer: openNetworkServer,
|
openNetworkServer: openNetworkServer,
|
||||||
}
|
}
|
||||||
@ -53,7 +56,7 @@ func (l *LocalClientConnection) Open(_, saveFilePath string) error {
|
|||||||
|
|
||||||
l.SetPlayerState(d2player.LoadPlayerState(saveFilePath))
|
l.SetPlayerState(d2player.LoadPlayerState(saveFilePath))
|
||||||
|
|
||||||
l.gameServer, err = d2server.NewGameServer(l.openNetworkServer, 30)
|
l.gameServer, err = d2server.NewGameServer(l.asset, l.openNetworkServer, 30)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
@ -31,6 +33,7 @@ const (
|
|||||||
type GameClient struct {
|
type GameClient struct {
|
||||||
clientConnection ServerConnection // Abstract local/remote connection
|
clientConnection ServerConnection // Abstract local/remote connection
|
||||||
connectionType d2clientconnectiontype.ClientConnectionType // Type of connection (local or remote)
|
connectionType d2clientconnectiontype.ClientConnectionType // Type of connection (local or remote)
|
||||||
|
asset *d2asset.AssetManager
|
||||||
scriptEngine *d2script.ScriptEngine
|
scriptEngine *d2script.ScriptEngine
|
||||||
GameState *d2player.PlayerState // local player state
|
GameState *d2player.PlayerState // local player state
|
||||||
MapEngine *d2mapengine.MapEngine // Map and entities
|
MapEngine *d2mapengine.MapEngine // Map and entities
|
||||||
@ -41,9 +44,11 @@ type GameClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create constructs a new GameClient and returns a pointer to it.
|
// Create constructs a new GameClient and returns a pointer to it.
|
||||||
func Create(connectionType d2clientconnectiontype.ClientConnectionType, scriptEngine *d2script.ScriptEngine) (*GameClient, error) {
|
func Create(connectionType d2clientconnectiontype.ClientConnectionType,
|
||||||
|
asset *d2asset.AssetManager, scriptEngine *d2script.ScriptEngine) (*GameClient, error) {
|
||||||
result := &GameClient{
|
result := &GameClient{
|
||||||
MapEngine: d2mapengine.CreateMapEngine(), // TODO: Mapgen - Needs levels.txt stuff
|
asset: asset,
|
||||||
|
MapEngine: d2mapengine.CreateMapEngine(asset), // TODO: Mapgen - Needs levels.txt stuff
|
||||||
Players: make(map[string]*d2mapentity.Player),
|
Players: make(map[string]*d2mapentity.Player),
|
||||||
connectionType: connectionType,
|
connectionType: connectionType,
|
||||||
scriptEngine: scriptEngine,
|
scriptEngine: scriptEngine,
|
||||||
@ -53,9 +58,9 @@ func Create(connectionType d2clientconnectiontype.ClientConnectionType, scriptEn
|
|||||||
case d2clientconnectiontype.LANClient:
|
case d2clientconnectiontype.LANClient:
|
||||||
result.clientConnection = d2remoteclient.Create()
|
result.clientConnection = d2remoteclient.Create()
|
||||||
case d2clientconnectiontype.LANServer:
|
case d2clientconnectiontype.LANServer:
|
||||||
result.clientConnection = d2localclient.Create(true)
|
result.clientConnection = d2localclient.Create(asset, true)
|
||||||
case d2clientconnectiontype.Local:
|
case d2clientconnectiontype.Local:
|
||||||
result.clientConnection = d2localclient.Create(false)
|
result.clientConnection = d2localclient.Create(asset, false)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown client connection type specified: %d", connectionType)
|
return nil, fmt.Errorf("unknown client connection type specified: %d", connectionType)
|
||||||
}
|
}
|
||||||
@ -180,7 +185,7 @@ func (g *GameClient) handleAddPlayerPacket(packet d2netpacket.NetPacket) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newPlayer := d2mapentity.NewPlayer(player.ID, player.Name, player.X, player.Y, 0,
|
newPlayer := g.MapEngine.NewPlayer(player.ID, player.Name, player.X, player.Y, 0,
|
||||||
player.HeroType, player.Stats, &player.Equipment)
|
player.HeroType, player.Stats, &player.Equipment)
|
||||||
|
|
||||||
g.Players[newPlayer.ID()] = newPlayer
|
g.Players[newPlayer.ID()] = newPlayer
|
||||||
@ -195,7 +200,7 @@ func (g *GameClient) handleSpawnItemPacket(packet d2netpacket.NetPacket) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
itemEntity, err := d2mapentity.NewItem(item.X, item.Y, item.Codes...)
|
itemEntity, err := g.MapEngine.NewItem(item.X, item.Y, item.Codes...)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
g.MapEngine.AddEntity(itemEntity)
|
g.MapEngine.AddEntity(itemEntity)
|
||||||
@ -255,7 +260,7 @@ func (g *GameClient) handleCastSkillPacket(packet d2netpacket.NetPacket) error {
|
|||||||
player.ClearPath()
|
player.ClearPath()
|
||||||
|
|
||||||
// currently hardcoded to missile skill
|
// currently hardcoded to missile skill
|
||||||
missile, err := d2mapentity.NewMissile(
|
missile, err := g.MapEngine.NewMissile(
|
||||||
int(player.Position.X()),
|
int(player.Position.X()),
|
||||||
int(player.Position.Y()),
|
int(player.Position.Y()),
|
||||||
d2datadict.Missiles[playerCast.SkillID],
|
d2datadict.Missiles[playerCast.SkillID],
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
|
||||||
@ -42,6 +43,7 @@ type GameServer struct {
|
|||||||
networkServer bool
|
networkServer bool
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
asset *d2asset.AssetManager
|
||||||
mapEngines []*d2mapengine.MapEngine
|
mapEngines []*d2mapengine.MapEngine
|
||||||
scriptEngine *d2script.ScriptEngine
|
scriptEngine *d2script.ScriptEngine
|
||||||
seed int64
|
seed int64
|
||||||
@ -57,7 +59,9 @@ var singletonServer *GameServer
|
|||||||
// ctx: required context item
|
// ctx: required context item
|
||||||
// networkServer: true = 0.0.0.0 | false = 127.0.0.1
|
// networkServer: true = 0.0.0.0 | false = 127.0.0.1
|
||||||
// maxConnections (default: 8): maximum number of TCP connections allowed open
|
// maxConnections (default: 8): maximum number of TCP connections allowed open
|
||||||
func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, error) {
|
func NewGameServer(asset *d2asset.AssetManager, networkServer bool,
|
||||||
|
maxConnections ...int) (*GameServer,
|
||||||
|
error) {
|
||||||
if len(maxConnections) == 0 {
|
if len(maxConnections) == 0 {
|
||||||
maxConnections = []int{8}
|
maxConnections = []int{8}
|
||||||
}
|
}
|
||||||
@ -67,6 +71,7 @@ func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, erro
|
|||||||
gameServer := &GameServer{
|
gameServer := &GameServer{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
|
asset: asset,
|
||||||
connections: make(map[string]ClientConnection),
|
connections: make(map[string]ClientConnection),
|
||||||
networkServer: networkServer,
|
networkServer: networkServer,
|
||||||
maxConnections: maxConnections[0],
|
maxConnections: maxConnections[0],
|
||||||
@ -78,7 +83,7 @@ func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, erro
|
|||||||
|
|
||||||
// TODO: In order to support dedicated mode we need to load the levels txt and files. Revisit this once this we can
|
// TODO: In order to support dedicated mode we need to load the levels txt and files. Revisit this once this we can
|
||||||
// load files independent of the app.
|
// load files independent of the app.
|
||||||
mapEngine := d2mapengine.CreateMapEngine()
|
mapEngine := d2mapengine.CreateMapEngine(asset)
|
||||||
mapEngine.SetSeed(gameServer.seed)
|
mapEngine.SetSeed(gameServer.seed)
|
||||||
mapEngine.ResetMap(d2enum.RegionAct1Town, 100, 100) // TODO: Mapgen - Needs levels.txt stuff
|
mapEngine.ResetMap(d2enum.RegionAct1Town, 100, 100) // TODO: Mapgen - Needs levels.txt stuff
|
||||||
d2mapgen.GenerateAct1Overworld(mapEngine)
|
d2mapgen.GenerateAct1Overworld(mapEngine)
|
||||||
|
14
main.go
14
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
|
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
@ -28,13 +29,18 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize our providers
|
// NewAssetManager our providers
|
||||||
renderer, err := ebiten.CreateRenderer()
|
renderer, err := ebiten.CreateRenderer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
audio, err := ebiten2.CreateAudio()
|
asset, err := d2asset.NewAssetManager(renderer, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
audio, err := ebiten2.CreateAudio(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -46,9 +52,11 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asset.BindTerminalCommands(term)
|
||||||
|
|
||||||
scriptEngine := d2script.CreateScriptEngine()
|
scriptEngine := d2script.CreateScriptEngine()
|
||||||
|
|
||||||
app := d2app.Create(GitBranch, GitCommit, inputManager, term, scriptEngine, audio, renderer)
|
app := d2app.Create(GitBranch, GitCommit, inputManager, term, scriptEngine, audio, renderer, asset)
|
||||||
if err := app.Run(); err != nil {
|
if err := app.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user