1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-15 20:15:24 +00:00
OpenDiablo2/d2game/d2gamescreen/character_select.go

457 lines
14 KiB
Go
Raw Normal View History

package d2gamescreen
import (
"fmt"
"image/color"
2019-11-13 04:44:04 +00:00
"math"
"os"
2020-06-28 23:31:10 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
)
// CharacterSelect represents the character select screen
type CharacterSelect struct {
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
2020-09-12 20:51:30 +00:00
asset *d2asset.AssetManager
*d2mapentity.MapEntityFactory
background *d2ui.Sprite
newCharButton *d2ui.Button
convertCharButton *d2ui.Button
deleteCharButton *d2ui.Button
exitButton *d2ui.Button
okButton *d2ui.Button
deleteCharCancelButton *d2ui.Button
deleteCharOkButton *d2ui.Button
selectionBox *d2ui.Sprite
okCancelBox *d2ui.Sprite
d2HeroTitle *d2ui.Label
deleteCharConfirmLabel *d2ui.Label
charScrollbar *d2ui.Scrollbar
characterNameLabel [8]*d2ui.Label
characterStatsLabel [8]*d2ui.Label
characterExpLabel [8]*d2ui.Label
2020-06-21 22:40:37 +00:00
characterImage [8]*d2mapentity.Player
2020-06-18 18:11:04 +00:00
gameStates []*d2player.PlayerState
selectedCharacter int
showDeleteConfirmation bool
2020-06-18 18:11:04 +00:00
connectionType d2clientconnectiontype.ClientConnectionType
connectionHost string
uiManager *d2ui.UIManager
inputManager d2interface.InputManager
audioProvider d2interface.AudioProvider
renderer d2interface.Renderer
navigator Navigator
}
// CreateCharacterSelect creates the character select screen and returns a pointer to it
func CreateCharacterSelect(
navigator Navigator,
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
2020-09-12 20:51:30 +00:00
asset *d2asset.AssetManager,
renderer d2interface.Renderer,
inputManager d2interface.InputManager,
audioProvider d2interface.AudioProvider,
ui *d2ui.UIManager,
connectionType d2clientconnectiontype.ClientConnectionType,
connectionHost string,
) *CharacterSelect {
2020-06-18 18:11:04 +00:00
return &CharacterSelect{
selectedCharacter: -1,
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
2020-09-12 20:51:30 +00:00
asset: asset,
MapEntityFactory: d2mapentity.NewMapEntityFactory(asset),
renderer: renderer,
2020-06-18 18:11:04 +00:00
connectionType: connectionType,
connectionHost: connectionHost,
inputManager: inputManager,
2020-06-28 23:31:10 +00:00
audioProvider: audioProvider,
navigator: navigator,
uiManager: ui,
2020-06-18 18:11:04 +00:00
}
}
const (
tenPercent = 0.1 * iota
twentyPercent
thirtyPercent
fourtyPercent
fiftyPercent
sixtyPercent
seventyPercent
eightyPercent
ninetyPercent
)
const (
rootLabelOffsetX = 115
rootLabelOffsetY = 100
labelHeight = 15
)
const (
selectionBoxNumColumns = 2
selectionBoxNumRows = 4
selectionBoxWidth = 272
selectionBoxHeight = 92
selectionBoxOffsetX = 37
selectionBoxOffsetY = 86
selectionBoxImageOffsetX = 40
selectionBoxImageOffsetY = 50
)
const (
blackHalfOpacity = 0x0000007f
lightBrown = 0xbca88cff
lightGreen = 0x18ff00ff
)
const (
screenWidth = 800
screenHeight = 600
)
const (
newCharBtnX, newCharBtnY = 33, 468
convertCharBtnX, convertCharBtnY = 233, 468
deleteCharBtnX, deleteCharBtnY = 433, 468
deleteCancelX, deleteCancelY = 282, 308
deleteOkX, deleteOkY = 422, 308
exitBtnX, exitBtnY = 33, 537
okBtnX, okBtnY = 625, 537
)
// OnLoad loads the resources for the Character Select screen
func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
2020-06-28 23:31:10 +00:00
v.audioProvider.PlayBGM(d2resource.BGMTitle)
if err := v.inputManager.BindHandler(v); err != nil {
fmt.Println("failed to add Character Select screen as event handler")
}
loading.Progress(tenPercent)
2020-02-09 02:02:37 +00:00
bgX, bgY := 0, 0
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
v.background, _ = v.uiManager.NewSprite(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
v.background.SetPosition(bgX, bgY)
2020-02-09 02:02:37 +00:00
v.createButtons(loading)
2020-02-09 02:02:37 +00:00
heroTitleX, heroTitleY := 320, 23
v.d2HeroTitle = v.uiManager.NewLabel(d2resource.Font42, d2resource.PaletteUnits)
v.d2HeroTitle.SetPosition(heroTitleX, heroTitleY)
v.d2HeroTitle.Alignment = d2gui.HorizontalAlignCenter
loading.Progress(thirtyPercent)
2020-02-09 02:02:37 +00:00
v.deleteCharConfirmLabel = v.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteUnits)
lines := "Are you sure that you want\nto delete this character?\nTake note: this will delete all\nversions of this Character."
v.deleteCharConfirmLabel.SetText(lines)
v.deleteCharConfirmLabel.Alignment = d2gui.HorizontalAlignCenter
deleteConfirmX, deleteConfirmY := 400, 185
v.deleteCharConfirmLabel.SetPosition(deleteConfirmX, deleteConfirmY)
2020-02-09 02:02:37 +00:00
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
v.selectionBox, _ = v.uiManager.NewSprite(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
selBoxX, selBoxY := 37, 86
v.selectionBox.SetPosition(selBoxX, selBoxY)
2020-02-09 02:02:37 +00:00
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
v.okCancelBox, _ = v.uiManager.NewSprite(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
okCancelX, okCancelY := 270, 175
v.okCancelBox.SetPosition(okCancelX, okCancelY)
2020-02-09 02:02:37 +00:00
scrollBarX, scrollBarY, scrollBarHeight := 586, 87, 369
v.charScrollbar = v.uiManager.NewScrollbar(scrollBarX, scrollBarY, scrollBarHeight)
2020-02-09 02:02:37 +00:00
v.charScrollbar.OnActivated(func() { v.onScrollUpdate() })
loading.Progress(fiftyPercent)
2020-02-09 02:02:37 +00:00
for i := 0; i < 8; i++ {
offsetX, offsetY := rootLabelOffsetX, rootLabelOffsetY+((i/2)*95)
2020-02-09 02:02:37 +00:00
if i&1 > 0 {
offsetX = 385
2020-02-09 02:02:37 +00:00
}
v.characterNameLabel[i] = v.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterNameLabel[i].SetPosition(offsetX, offsetY)
v.characterNameLabel[i].Color[0] = rgbaColor(lightBrown)
offsetY += labelHeight
v.characterStatsLabel[i] = v.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterStatsLabel[i].SetPosition(offsetX, offsetY)
offsetY += labelHeight
v.characterExpLabel[i] = v.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteStatic)
v.characterExpLabel[i].SetPosition(offsetX, offsetY)
v.characterExpLabel[i].Color[0] = rgbaColor(lightGreen)
}
2020-02-09 02:02:37 +00:00
v.refreshGameStates()
}
func rgbaColor(rgba uint32) color.RGBA {
result := color.RGBA{}
a, b, g, r := 0, 1, 2, 3
byteWidth := 8
byteMask := 0xff
for idx := 0; idx < 4; idx++ {
shift := idx * byteWidth
component := uint8(rgba>>shift) & uint8(byteMask)
switch idx {
case a:
result.A = component
case b:
result.B = component
case g:
result.G = component
case r:
result.R = component
}
}
return result
}
func (v *CharacterSelect) createButtons(loading d2screen.LoadingState) {
v.newCharButton = v.uiManager.NewButton(d2ui.ButtonTypeTall, "CREATE NEW\nCHARACTER")
v.newCharButton.SetPosition(newCharBtnX, newCharBtnY)
v.newCharButton.OnActivated(func() { v.onNewCharButtonClicked() })
v.convertCharButton = v.uiManager.NewButton(d2ui.ButtonTypeTall, "CONVERT TO\nEXPANSION")
v.convertCharButton.SetPosition(convertCharBtnX, convertCharBtnY)
v.convertCharButton.SetEnabled(false)
v.deleteCharButton = v.uiManager.NewButton(d2ui.ButtonTypeTall, "DELETE\nCHARACTER")
v.deleteCharButton.OnActivated(func() { v.onDeleteCharButtonClicked() })
v.deleteCharButton.SetPosition(deleteCharBtnX, deleteCharBtnY)
v.exitButton = v.uiManager.NewButton(d2ui.ButtonTypeMedium, "EXIT")
v.exitButton.SetPosition(exitBtnX, exitBtnY)
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
loading.Progress(twentyPercent)
v.deleteCharCancelButton = v.uiManager.NewButton(d2ui.ButtonTypeOkCancel, "NO")
v.deleteCharCancelButton.SetPosition(deleteCancelX, deleteCancelY)
v.deleteCharCancelButton.SetVisible(false)
v.deleteCharCancelButton.OnActivated(func() { v.onDeleteCharacterCancelClicked() })
v.deleteCharOkButton = v.uiManager.NewButton(d2ui.ButtonTypeOkCancel, "YES")
v.deleteCharOkButton.SetPosition(deleteOkX, deleteOkY)
v.deleteCharOkButton.SetVisible(false)
v.deleteCharOkButton.OnActivated(func() { v.onDeleteCharacterConfirmClicked() })
v.okButton = v.uiManager.NewButton(d2ui.ButtonTypeMedium, "OK")
v.okButton.SetPosition(okBtnX, okBtnY)
v.okButton.OnActivated(func() { v.onOkButtonClicked() })
}
2019-11-13 04:44:04 +00:00
func (v *CharacterSelect) onScrollUpdate() {
v.moveSelectionBox()
v.updateCharacterBoxes()
}
func (v *CharacterSelect) updateCharacterBoxes() {
expText := "EXPANSION CHARACTER"
for i := 0; i < 8; i++ {
2019-11-13 04:44:04 +00:00
idx := i + (v.charScrollbar.GetCurrentOffset() * 2)
if idx >= len(v.gameStates) {
v.characterNameLabel[i].SetText("")
v.characterStatsLabel[i].SetText("")
v.characterExpLabel[i].SetText("")
v.characterImage[i] = nil
continue
}
heroName := v.gameStates[idx].HeroName
heroInfo := "Level 1 " + v.gameStates[idx].HeroType.String()
v.characterNameLabel[i].SetText(d2ui.ColorTokenize(heroName, d2ui.ColorTokenGold))
v.characterStatsLabel[i].SetText(d2ui.ColorTokenize(heroInfo, d2ui.ColorTokenWhite))
v.characterExpLabel[i].SetText(d2ui.ColorTokenize(expText, d2ui.ColorTokenGreen))
heroType := v.gameStates[idx].HeroType
equipment := d2inventory.HeroObjects[heroType]
// TODO: Generate or load the object from the actual player data...
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
2020-09-12 20:51:30 +00:00
v.characterImage[i] = v.NewPlayer("", "", 0, 0, 0,
v.gameStates[idx].HeroType,
v.gameStates[idx].Stats,
&equipment,
2019-11-15 03:20:01 +00:00
)
}
}
2019-10-27 06:58:37 +00:00
func (v *CharacterSelect) onNewCharButtonClicked() {
v.navigator.ToSelectHero(v.connectionType, v.connectionHost)
2019-10-27 06:58:37 +00:00
}
func (v *CharacterSelect) onExitButtonClicked() {
v.navigator.ToMainMenu()
}
// Render renders the Character Select screen
func (v *CharacterSelect) Render(screen d2interface.Surface) error {
if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil {
return err
}
v.d2HeroTitle.Render(screen)
2019-11-13 04:44:04 +00:00
actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
2019-11-13 04:44:04 +00:00
if v.selectedCharacter > -1 && actualSelectionIndex >= 0 && actualSelectionIndex < 8 {
if err := v.selectionBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
}
}
for i := 0; i < 8; i++ {
2019-11-13 04:44:04 +00:00
idx := i + (v.charScrollbar.GetCurrentOffset() * 2)
if idx >= len(v.gameStates) {
continue
}
v.characterNameLabel[i].Render(screen)
v.characterStatsLabel[i].Render(screen)
v.characterExpLabel[i].Render(screen)
charImgX := v.characterNameLabel[i].X - selectionBoxImageOffsetX
charImgY := v.characterNameLabel[i].Y + selectionBoxImageOffsetY
screen.PushTranslation(charImgX, charImgY)
v.characterImage[i].Render(screen)
screen.Pop()
}
if v.showDeleteConfirmation {
screen.DrawRect(screenWidth, screenHeight, rgbaColor(blackHalfOpacity))
if err := v.okCancelBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
}
v.deleteCharConfirmLabel.Render(screen)
}
2020-02-09 02:02:37 +00:00
return nil
}
func (v *CharacterSelect) moveSelectionBox() {
2019-11-13 04:44:04 +00:00
if v.selectedCharacter == -1 {
v.d2HeroTitle.SetText("")
return
}
bw := 272
bh := 92
2019-11-13 04:44:04 +00:00
selectedIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
selBoxX := selectionBoxOffsetX + ((selectedIndex & 1) * bw)
selBoxY := selectionBoxOffsetY + (bh * (selectedIndex / 2))
v.selectionBox.SetPosition(selBoxX, selBoxY)
v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName)
}
// OnMouseButtonDown is called when a mouse button is clicked
func (v *CharacterSelect) OnMouseButtonDown(event d2interface.MouseEvent) bool {
if !v.showDeleteConfirmation {
if event.Button() == d2enum.MouseButtonLeft {
mx, my := event.X(), event.Y()
bw := selectionBoxWidth
bh := selectionBoxHeight
localMouseX := mx - selectionBoxOffsetX
localMouseY := my - selectionBoxOffsetY
if localMouseX > 0 && localMouseX < bw*2 && localMouseY >= 0 && localMouseY < bh*4 {
adjustY := localMouseY / bh
selectedIndex := adjustY * selectionBoxNumColumns
if localMouseX > bw {
selectedIndex++
}
if (v.charScrollbar.GetCurrentOffset()*2)+selectedIndex < len(v.gameStates) {
v.selectedCharacter = (v.charScrollbar.GetCurrentOffset() * 2) + selectedIndex
v.moveSelectionBox()
}
}
return true
}
}
return false
}
// Advance runs the update logic on the Character Select screen
func (v *CharacterSelect) Advance(tickTime float64) error {
for _, hero := range v.characterImage {
if hero != nil {
hero.Advance(tickTime)
}
}
2020-02-09 02:02:37 +00:00
return nil
}
func (v *CharacterSelect) onDeleteCharButtonClicked() {
v.toggleDeleteCharacterDialog(true)
}
func (v *CharacterSelect) onDeleteCharacterConfirmClicked() {
_ = os.Remove(v.gameStates[v.selectedCharacter].FilePath)
2019-11-13 04:44:04 +00:00
v.charScrollbar.SetCurrentOffset(0)
v.refreshGameStates()
v.toggleDeleteCharacterDialog(false)
2019-11-13 04:44:04 +00:00
v.deleteCharButton.SetEnabled(len(v.gameStates) > 0)
v.okButton.SetEnabled(len(v.gameStates) > 0)
}
func (v *CharacterSelect) onDeleteCharacterCancelClicked() {
v.toggleDeleteCharacterDialog(false)
}
func (v *CharacterSelect) toggleDeleteCharacterDialog(showDialog bool) {
v.showDeleteConfirmation = showDialog
v.okButton.SetEnabled(!showDialog)
v.deleteCharButton.SetEnabled(!showDialog)
v.exitButton.SetEnabled(!showDialog)
v.newCharButton.SetEnabled(!showDialog)
v.deleteCharOkButton.SetVisible(showDialog)
v.deleteCharCancelButton.SetVisible(showDialog)
}
func (v *CharacterSelect) refreshGameStates() {
2020-06-18 18:11:04 +00:00
v.gameStates = d2player.GetAllPlayerStates()
v.updateCharacterBoxes()
if len(v.gameStates) > 0 {
v.selectedCharacter = 0
numStates := selectionBoxNumColumns * selectionBoxNumRows
byHalf := 2.0
v.d2HeroTitle.SetText(v.gameStates[0].HeroName)
v.charScrollbar.SetMaxOffset(int(math.Ceil(float64(len(v.gameStates)-numStates) / byHalf)))
} else {
v.selectedCharacter = -1
2019-11-13 04:44:04 +00:00
v.charScrollbar.SetMaxOffset(0)
}
v.moveSelectionBox()
}
2019-11-13 05:31:52 +00:00
func (v *CharacterSelect) onOkButtonClicked() {
v.navigator.ToCreateGame(v.gameStates[v.selectedCharacter].FilePath, v.connectionType, v.connectionHost)
2019-11-13 05:31:52 +00:00
}