1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-18 13:15:24 +00:00

Lint fixes for the d2game/d2gamescreen (#516)

* more lint fixes for the d2core/d2term

* lint fixes for the escape_menu.go

* fixed lint issues of credits screen

* more lint fixes for the d2gamescreen

* lint fixes for the main menu of d2game/d2gamescreen package

* lint fixes for the main menu and map engine testing of d2game/d2gamescreen package

* more lint fixes for the main menu of d2game/d2gamescreen package

* lint fixes for the character select screen of d2game/d2gamescreen package
This commit is contained in:
Gürkan Kaymak 2020-07-02 20:55:43 +03:00 committed by GitHub
parent 8e2c7d1f38
commit 9c2b1dccaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 636 additions and 392 deletions

View File

@ -1,3 +1,4 @@
// Package d2term provides a in-game terminal that allows executing custom commands for debugging
package d2term
import (
@ -45,6 +46,11 @@ const (
termVisHiding
)
const (
maxVisAnim = 1.0
minVisAnim = 0.0
)
type termHistoryEntry struct {
text string
category d2interface.TermCategory
@ -79,13 +85,13 @@ type terminal struct {
func (t *terminal) Advance(elapsed float64) error {
switch t.visState {
case termVisShowing:
t.visAnim = math.Min(1.0, t.visAnim+elapsed/termAnimLength)
if t.visAnim == 1.0 {
t.visAnim = math.Min(maxVisAnim, t.visAnim+elapsed/termAnimLength)
if t.visAnim == maxVisAnim {
t.visState = termVisShown
}
case termVisHiding:
t.visAnim = math.Max(0.0, t.visAnim-elapsed/termAnimLength)
if t.visAnim == 0.0 {
t.visAnim = math.Max(minVisAnim, t.visAnim-elapsed/termAnimLength)
if t.visAnim == minVisAnim {
t.visState = termVisHidden
}
}
@ -122,12 +128,8 @@ func (t *terminal) OnKeyDown(event d2input.KeyEvent) bool {
if t.outputIndex -= t.lineCount; t.outputIndex < 0 {
t.outputIndex = 0
}
case d2input.KeyUp:
t.handleKeyUp(event.KeyMod)
case d2input.KeyDown:
if event.KeyMod == d2input.KeyModControl {
t.lineCount = d2common.MinInt(t.lineCount+1, termRowCountMax)
}
case d2input.KeyUp, d2input.KeyDown:
t.handleControlKey(event.Key, event.KeyMod)
case d2input.KeyEnter:
t.processCommand()
case d2input.KeyBackspace:
@ -166,15 +168,22 @@ func (t *terminal) processCommand() {
t.command = ""
}
func (t *terminal) handleKeyUp(keyMod d2input.KeyMod) {
if keyMod == d2input.KeyModControl {
t.lineCount = d2common.MaxInt(0, t.lineCount-1)
} else if len(t.commandHistory) > 0 {
t.command = t.commandHistory[t.commandIndex]
if t.commandIndex == 0 {
t.commandIndex = len(t.commandHistory) - 1
} else {
t.commandIndex--
func (t *terminal) handleControlKey(eventKey d2input.Key, keyMod d2input.KeyMod) {
switch eventKey {
case d2input.KeyUp:
if keyMod == d2input.KeyModControl {
t.lineCount = d2common.MaxInt(0, t.lineCount-1)
} else if len(t.commandHistory) > 0 {
t.command = t.commandHistory[t.commandIndex]
if t.commandIndex == 0 {
t.commandIndex = len(t.commandHistory) - 1
} else {
t.commandIndex--
}
}
case d2input.KeyDown:
if keyMod == d2input.KeyModControl {
t.lineCount = d2common.MinInt(t.lineCount+1, termRowCountMax)
}
}
}
@ -276,45 +285,9 @@ func (t *terminal) Execute(command string) error {
return errors.New("action requires different argument count")
}
var paramValues []reflect.Value
for i := 0; i < actionType.NumIn(); i++ {
actionParam := actionParams[i]
switch actionType.In(i).Kind() {
case reflect.String:
paramValues = append(paramValues, reflect.ValueOf(actionParam))
case reflect.Int:
value, err := strconv.ParseInt(actionParam, 10, 64)
if err != nil {
return err
}
paramValues = append(paramValues, reflect.ValueOf(int(value)))
case reflect.Uint:
value, err := strconv.ParseUint(actionParam, 10, 64)
if err != nil {
return err
}
paramValues = append(paramValues, reflect.ValueOf(uint(value)))
case reflect.Float64:
value, err := strconv.ParseFloat(actionParam, 64)
if err != nil {
return err
}
paramValues = append(paramValues, reflect.ValueOf(value))
case reflect.Bool:
value, err := strconv.ParseBool(actionParam)
if err != nil {
return err
}
paramValues = append(paramValues, reflect.ValueOf(value))
default:
return errors.New("action has unsupported arguments")
}
paramValues, err := parseActionParams(actionType, actionParams)
if err != nil {
return err
}
actionValue := reflect.ValueOf(actionEntry.action)
@ -331,6 +304,51 @@ func (t *terminal) Execute(command string) error {
return nil
}
func parseActionParams(actionType reflect.Type, actionParams []string) ([]reflect.Value, error) {
var paramValues []reflect.Value
for i := 0; i < actionType.NumIn(); i++ {
actionParam := actionParams[i]
switch actionType.In(i).Kind() {
case reflect.String:
paramValues = append(paramValues, reflect.ValueOf(actionParam))
case reflect.Int:
value, err := strconv.ParseInt(actionParam, 10, 64)
if err != nil {
return nil, err
}
paramValues = append(paramValues, reflect.ValueOf(int(value)))
case reflect.Uint:
value, err := strconv.ParseUint(actionParam, 10, 64)
if err != nil {
return nil, err
}
paramValues = append(paramValues, reflect.ValueOf(uint(value)))
case reflect.Float64:
value, err := strconv.ParseFloat(actionParam, 64)
if err != nil {
return nil, err
}
paramValues = append(paramValues, reflect.ValueOf(value))
case reflect.Bool:
value, err := strconv.ParseBool(actionParam)
if err != nil {
return nil, err
}
paramValues = append(paramValues, reflect.ValueOf(value))
default:
return nil, errors.New("action has unsupported arguments")
}
}
return paramValues, nil
}
func (t *terminal) OutputRaw(text string, category d2interface.TermCategory) {
var line string

View File

@ -1,6 +1,7 @@
package d2gamescreen
import (
"fmt"
"image/color"
"math"
"os"
@ -22,6 +23,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
)
// CharacterSelect represents the character select screen
type CharacterSelect struct {
background *d2ui.Sprite
newCharButton d2ui.Button
@ -49,8 +51,12 @@ type CharacterSelect struct {
terminal d2interface.Terminal
}
func CreateCharacterSelect(audioProvider d2interface.AudioProvider,
connectionType d2clientconnectiontype.ClientConnectionType, connectionHost string, term d2interface.Terminal) *CharacterSelect {
// CreateCharacterSelect creates the character select screen and returns a pointer to it
func CreateCharacterSelect(
audioProvider d2interface.AudioProvider,
connectionType d2clientconnectiontype.ClientConnectionType,
connectionHost string, term d2interface.Terminal,
) *CharacterSelect {
return &CharacterSelect{
selectedCharacter: -1,
connectionType: connectionType,
@ -60,26 +66,89 @@ func CreateCharacterSelect(audioProvider d2interface.AudioProvider,
}
}
// OnLoad loads the resources for the Character Select screen
func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
v.audioProvider.PlayBGM(d2resource.BGMTitle)
d2input.BindHandler(v)
if err := d2input.BindHandler(v); err != nil {
fmt.Println("failed to add Character Select screen as event handler")
}
loading.Progress(0.1)
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0)
v.newCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("CREATE NEW CHARACTER", 15)))
v.createButtons(loading)
v.d2HeroTitle = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.d2HeroTitle.SetPosition(320, 23)
v.d2HeroTitle.Alignment = d2ui.LabelAlignCenter
loading.Progress(0.3)
v.deleteCharConfirmLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
lines := d2common.SplitIntoLinesWithMaxWidth(
"Are you sure that you want to delete this character? Take note: this will delete all versions of this Character.",
29,
)
v.deleteCharConfirmLabel.SetText(strings.Join(lines, "\n"))
v.deleteCharConfirmLabel.Alignment = d2ui.LabelAlignCenter
v.deleteCharConfirmLabel.SetPosition(400, 185)
animation, _ = d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
v.selectionBox, _ = d2ui.LoadSprite(animation)
v.selectionBox.SetPosition(37, 86)
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.okCancelBox, _ = d2ui.LoadSprite(animation)
v.okCancelBox.SetPosition(270, 175)
v.charScrollbar = d2ui.CreateScrollbar(586, 87, 369)
v.charScrollbar.OnActivated(func() { v.onScrollUpdate() })
d2ui.AddWidget(&v.charScrollbar)
loading.Progress(0.5)
for i := 0; i < 8; i++ {
xOffset := 115
if i&1 > 0 {
xOffset = 385
}
v.characterNameLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterNameLabel[i].Color = color.RGBA{R: 188, G: 168, B: 140, A: 255}
v.characterNameLabel[i].SetPosition(xOffset, 100+((i/2)*95))
v.characterStatsLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterStatsLabel[i].SetPosition(xOffset, 115+((i/2)*95))
v.characterExpLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteStatic)
v.characterExpLabel[i].Color = color.RGBA{R: 24, G: 255, A: 255}
v.characterExpLabel[i].SetPosition(xOffset, 130+((i/2)*95))
}
v.refreshGameStates()
}
func (v *CharacterSelect) createButtons(loading d2screen.LoadingState) {
v.newCharButton = d2ui.CreateButton(
d2ui.ButtonTypeTall,
d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("CREATE NEW CHARACTER", 15)),
)
v.newCharButton.SetPosition(33, 468)
v.newCharButton.OnActivated(func() { v.onNewCharButtonClicked() })
d2ui.AddWidget(&v.newCharButton)
v.convertCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("CONVERT TO EXPANSION", 15)))
v.convertCharButton = d2ui.CreateButton(
d2ui.ButtonTypeTall,
d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("CONVERT TO EXPANSION", 15)),
)
v.convertCharButton.SetPosition(233, 468)
v.convertCharButton.SetEnabled(false)
d2ui.AddWidget(&v.convertCharButton)
v.deleteCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("DELETE CHARACTER", 15)))
v.deleteCharButton = d2ui.CreateButton(
d2ui.ButtonTypeTall,
d2common.CombineStrings(d2common.SplitIntoLinesWithMaxWidth("DELETE CHARACTER", 15)),
)
v.deleteCharButton.OnActivated(func() { v.onDeleteCharButtonClicked() })
v.deleteCharButton.SetPosition(433, 468)
d2ui.AddWidget(&v.deleteCharButton)
@ -106,46 +175,6 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
v.okButton.SetPosition(625, 537)
v.okButton.OnActivated(func() { v.onOkButtonClicked() })
d2ui.AddWidget(&v.okButton)
v.d2HeroTitle = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.d2HeroTitle.SetPosition(320, 23)
v.d2HeroTitle.Alignment = d2ui.LabelAlignCenter
loading.Progress(0.3)
v.deleteCharConfirmLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
lines := d2common.SplitIntoLinesWithMaxWidth("Are you sure that you want to delete this character? Take note: this will delete all versions of this Character.", 29)
v.deleteCharConfirmLabel.SetText(strings.Join(lines, "\n"))
v.deleteCharConfirmLabel.Alignment = d2ui.LabelAlignCenter
v.deleteCharConfirmLabel.SetPosition(400, 185)
animation, _ = d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
v.selectionBox, _ = d2ui.LoadSprite(animation)
v.selectionBox.SetPosition(37, 86)
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.okCancelBox, _ = d2ui.LoadSprite(animation)
v.okCancelBox.SetPosition(270, 175)
v.charScrollbar = d2ui.CreateScrollbar(586, 87, 369)
v.charScrollbar.OnActivated(func() { v.onScrollUpdate() })
d2ui.AddWidget(&v.charScrollbar)
loading.Progress(0.5)
for i := 0; i < 8; i++ {
xOffset := 115
if i&1 > 0 {
xOffset = 385
}
v.characterNameLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterNameLabel[i].Color = color.RGBA{R: 188, G: 168, B: 140, A: 255}
v.characterNameLabel[i].SetPosition(xOffset, 100+((i/2)*95))
v.characterStatsLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.characterStatsLabel[i].SetPosition(xOffset, 115+((i/2)*95))
v.characterExpLabel[i] = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteStatic)
v.characterExpLabel[i].Color = color.RGBA{R: 24, G: 255, A: 255}
v.characterExpLabel[i].SetPosition(xOffset, 130+((i/2)*95))
}
v.refreshGameStates()
}
func (v *CharacterSelect) onScrollUpdate() {
@ -155,6 +184,7 @@ func (v *CharacterSelect) onScrollUpdate() {
func (v *CharacterSelect) updateCharacterBoxes() {
expText := "EXPANSION CHARACTER"
for i := 0; i < 8; i++ {
idx := i + (v.charScrollbar.GetCurrentOffset() * 2)
if idx >= len(v.gameStates) {
@ -162,8 +192,10 @@ func (v *CharacterSelect) updateCharacterBoxes() {
v.characterStatsLabel[i].SetText("")
v.characterExpLabel[i].SetText("")
v.characterImage[i] = nil
continue
}
v.characterNameLabel[i].SetText(v.gameStates[idx].HeroName)
v.characterStatsLabel[i].SetText("Level 1 " + v.gameStates[idx].HeroType.String())
v.characterExpLabel[i].SetText(expText)
@ -182,22 +214,31 @@ func (v *CharacterSelect) onNewCharButtonClicked() {
func (v *CharacterSelect) onExitButtonClicked() {
mainMenu := CreateMainMenu(v.audioProvider, v.terminal)
mainMenu.SetScreenMode(ScreenModeMainMenu)
mainMenu.setScreenMode(screenModeMainMenu)
d2screen.SetNextScreen(mainMenu)
}
// Render renders the Character Select screen
func (v *CharacterSelect) Render(screen d2interface.Surface) error {
v.background.RenderSegmented(screen, 4, 3, 0)
if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil {
return err
}
v.d2HeroTitle.Render(screen)
actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
if v.selectedCharacter > -1 && actualSelectionIndex >= 0 && actualSelectionIndex < 8 {
v.selectionBox.RenderSegmented(screen, 2, 1, 0)
if err := v.selectionBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
}
}
for i := 0; i < 8; i++ {
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)
@ -205,9 +246,14 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) error {
v.characterImage[i].Render(screen)
screen.Pop()
}
if v.showDeleteConfirmation {
screen.DrawRect(800, 600, color.RGBA{A: 128})
v.okCancelBox.RenderSegmented(screen, 2, 1, 0)
if err := v.okCancelBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
}
v.deleteCharConfirmLabel.Render(screen)
}
@ -219,6 +265,7 @@ func (v *CharacterSelect) moveSelectionBox() {
v.d2HeroTitle.SetText("")
return
}
bw := 272
bh := 92
selectedIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
@ -226,6 +273,7 @@ func (v *CharacterSelect) moveSelectionBox() {
v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName)
}
// OnMouseButtonDown is called when a mouse button is clicked
func (v *CharacterSelect) OnMouseButtonDown(event d2input.MouseEvent) bool {
if !v.showDeleteConfirmation {
if event.Button == d2input.MouseButtonLeft {
@ -234,23 +282,29 @@ func (v *CharacterSelect) OnMouseButtonDown(event d2input.MouseEvent) bool {
bh := 92
localMouseX := mx - 37
localMouseY := my - 86
if localMouseX > 0 && localMouseX < bw*2 && localMouseY >= 0 && localMouseY < bh*4 {
adjustY := localMouseY / bh
selectedIndex := adjustY * 2
if localMouseX > bw {
selectedIndex += 1
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 {
@ -291,6 +345,7 @@ func (v *CharacterSelect) toggleDeleteCharacterDialog(showDialog bool) {
func (v *CharacterSelect) refreshGameStates() {
v.gameStates = d2player.GetAllPlayerStates()
v.updateCharacterBoxes()
if len(v.gameStates) > 0 {
v.selectedCharacter = 0
v.d2HeroTitle.SetText(v.gameStates[0].HeroName)
@ -299,17 +354,21 @@ func (v *CharacterSelect) refreshGameStates() {
v.selectedCharacter = -1
v.charScrollbar.SetMaxOffset(0)
}
v.moveSelectionBox()
v.moveSelectionBox()
}
func (v *CharacterSelect) onOkButtonClicked() {
gameClient, _ := d2client.Create(v.connectionType)
switch v.connectionType {
case d2clientconnectiontype.LANClient:
gameClient.Open(v.connectionHost, v.gameStates[v.selectedCharacter].FilePath)
default:
gameClient.Open("", v.gameStates[v.selectedCharacter].FilePath)
host := ""
if v.connectionType == d2clientconnectiontype.LANClient {
host = v.connectionHost
}
if err := gameClient.Open(host, v.gameStates[v.selectedCharacter].FilePath); err != nil {
// TODO an error screen should be shown in this case
fmt.Printf("can not connect to the host: %s", host)
}
d2screen.SetNextScreen(CreateGame(v.audioProvider, gameClient, v.terminal))

View File

@ -2,6 +2,7 @@ package d2gamescreen
import (
"bufio"
"fmt"
"image/color"
"log"
"os"
@ -46,24 +47,32 @@ func CreateCredits(audioProvider d2interface.AudioProvider) *Credits {
cyclesTillNextLine: 0,
audioProvider: audioProvider,
}
return result
}
// Load is called to load the contributors data from file
// LoadContributors loads the contributors data from file
// TODO: use markdown for file and convert it to the suitable format
func (v *Credits) LoadContributors() []string {
var contributors []string
file, err := os.Open(path.Join("./", "CONTRIBUTORS"))
if err != nil || file == nil {
log.Print("CONTRIBUTORS file is missing")
return []string{"MISSING CONTRIBUTOR FILES!"}
}
defer file.Close()
defer func() {
if err = file.Close(); err != nil {
fmt.Printf("an error occurred while closing file: %s, err: %q\n", file.Name(), err)
}
}()
scanner := bufio.NewScanner(file)
var contributors []string
for scanner.Scan() {
contributors = append(contributors, strings.Trim(scanner.Text(), " "))
}
return contributors
}
@ -85,13 +94,16 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
loading.Error(err)
return
}
loading.Progress(0.6)
creditData, _ := d2common.Utf16BytesToString(fileData[2:])
v.creditsText = strings.Split(creditData, "\r\n")
for i := range v.creditsText {
v.creditsText[i] = strings.Trim(v.creditsText[i], " ")
}
loading.Progress(0.8)
v.creditsText = append(v.LoadContributors(), v.creditsText...)
@ -99,11 +111,16 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
// Render renders the credits screen
func (v *Credits) Render(screen d2interface.Surface) error {
v.creditsBackground.RenderSegmented(screen, 4, 3, 0)
err := v.creditsBackground.RenderSegmented(screen, 4, 3, 0)
if err != nil {
return err
}
for _, label := range v.labels {
if label.Available {
continue
}
label.Label.Render(screen)
}
@ -112,12 +129,13 @@ func (v *Credits) Render(screen d2interface.Surface) error {
const secondsPerCycle = float64(0.02)
// Update runs the update logic on the credits screen
// Advance runs the update logic on the credits screen
func (v *Credits) Advance(tickTime float64) error {
v.cycleTime += tickTime
for v.cycleTime >= secondsPerCycle {
v.cycleTime -= secondsPerCycle
v.cyclesTillNextLine--
if !v.doneWithCredits && v.cyclesTillNextLine <= 0 {
v.addNextItem()
}
@ -126,6 +144,7 @@ func (v *Credits) Advance(tickTime float64) error {
if label.Available {
continue
}
if label.Label.Y-1 < -15 {
label.Available = true
continue
@ -139,7 +158,7 @@ func (v *Credits) Advance(tickTime float64) error {
func (v *Credits) onExitButtonClicked() {
mainMenu := CreateMainMenu(v.audioProvider, v.terminal)
mainMenu.SetScreenMode(ScreenModeMainMenu)
mainMenu.setScreenMode(screenModeMainMenu)
d2screen.SetNextScreen(mainMenu)
}
@ -151,55 +170,71 @@ func (v *Credits) addNextItem() {
text := v.creditsText[0]
v.creditsText = v.creditsText[1:]
if len(text) == 0 && v.creditsText[0][0] != '*' {
if text == "" {
if v.creditsText[0][0] == '*' {
v.cyclesTillNextLine = 38
return
}
v.cyclesTillNextLine = 19
return
} else if len(text) == 0 && v.creditsText[0][0] == '*' {
v.cyclesTillNextLine = 38
return
}
isHeading := text[0] == '*'
isNextHeading := len(v.creditsText) > 0 && len(v.creditsText[0]) > 0 && v.creditsText[0][0] == '*'
isNextSpace := len(v.creditsText) > 0 && len(v.creditsText[0]) == 0
isNextSpace := len(v.creditsText) > 0 && v.creditsText[0] == ""
var label = v.getNewFontLabel(isHeading)
if isHeading {
label.SetText(text[1:])
} else {
label.SetText(text)
}
isDoubled, isNextHeading := v.setItemLabelPosition(label, isHeading, isNextHeading, isNextSpace)
switch {
case isHeading && isNextHeading:
v.cyclesTillNextLine = 38
case isNextHeading:
if isDoubled {
v.cyclesTillNextLine = 38
} else {
v.cyclesTillNextLine = 57
}
case isHeading:
v.cyclesTillNextLine = 38
default:
v.cyclesTillNextLine = 19
}
}
func (v *Credits) setItemLabelPosition(label *d2ui.Label, isHeading, isNextHeading, isNextSpace bool) (isDoubled, nextHeading bool) {
width, _ := label.GetSize()
isDoubled := false
if !isHeading && !isNextHeading && !isNextSpace {
isDoubled = true
// Gotta go side by side
label.SetPosition(400-width, 605)
text2 := v.creditsText[0]
v.creditsText = v.creditsText[1:]
isNextHeading = len(v.creditsText) > 0 && len(v.creditsText[0]) > 0 && v.creditsText[0][0] == '*'
nextHeading = len(v.creditsText) > 0 && len(v.creditsText[0]) > 0 && v.creditsText[0][0] == '*'
label2 := v.getNewFontLabel(isHeading)
label2.SetText(text2)
label2.SetPosition(410, 605)
} else {
label.SetPosition(405-width/2, 605)
return isDoubled, nextHeading
}
if isHeading && isNextHeading {
v.cyclesTillNextLine = 38
} else if isNextHeading {
if isDoubled {
v.cyclesTillNextLine = 38
} else {
v.cyclesTillNextLine = 57
}
} else if isHeading {
v.cyclesTillNextLine = 38
} else {
v.cyclesTillNextLine = 19
}
label.SetPosition(405-width/2, 605)
return isDoubled, isNextHeading
}
func (v *Credits) getNewFontLabel(isHeading bool) *d2ui.Label {
@ -211,6 +246,7 @@ func (v *Credits) getNewFontLabel(isHeading bool) *d2ui.Label {
} else {
label.Label.Color = color.RGBA{R: 198, G: 178, B: 150, A: 255}
}
return &label.Label
}
}
@ -225,9 +261,9 @@ func (v *Credits) getNewFontLabel(isHeading bool) *d2ui.Label {
newLabelItem.Label.Color = color.RGBA{R: 255, G: 88, B: 82, A: 255}
} else {
newLabelItem.Label.Color = color.RGBA{R: 198, G: 178, B: 150, A: 255}
}
v.labels = append(v.labels, newLabelItem)
return &newLabelItem.Label
}

View File

@ -26,35 +26,38 @@ const (
menuSize = 500
// layouts
noLayoutID layoutID = -2
saveLayoutID = -1
mainLayoutID = 0
optionsLayoutID = 1
soundOptionsLayoutID = 2
videoOptionsLayoutID = 3
automapOptionsLayoutID = 4
configureControlsLayoutID = 5
noLayoutID layoutID = iota - 2
saveLayoutID
mainLayoutID
optionsLayoutID
soundOptionsLayoutID
videoOptionsLayoutID
automapOptionsLayoutID
configureControlsLayoutID
// options
optAudioSoundVolume optionID = 0 // audio
optAudioMusicVolume = 1
optAudio3dSound = 2
optAudioHardwareAcceleration = 3
optAudioEnvEffects = 4
optAudioNpcSpeech = 5
optVideoResolution = 6 // video
optVideoLightingQuality = 7
optVideoBlendedShadows = 8
optVideoPerspective = 9
optVideoGamma = 10
optVideoContrast = 11
optAutomapSize = 12 // automap
optAutomapFade = 13
optAutomapCenterWhenCleared = 14
optAutomapShowParty = 15
optAutomapShowNames = 16
// audio
optAudioSoundVolume optionID = iota
optAudioMusicVolume
optAudio3dSound
optAudioHardwareAcceleration
optAudioEnvEffects
optAudioNpcSpeech
// video
optVideoResolution
optVideoLightingQuality
optVideoBlendedShadows
optVideoPerspective
optVideoGamma
optVideoContrast
// automap
optAutomapSize
optAutomapFade
optAutomapCenterWhenCleared
optAutomapShowParty
optAutomapShowNames
)
// EscapeMenu represents the in-game menu that shows up when the esc key is pressed
type EscapeMenu struct {
isOpen bool
selectSound d2interface.SoundEffect
@ -104,8 +107,13 @@ func (l *enumLabel) Trigger() {
l.playSound()
next := (l.current + 1) % len(l.values)
l.current = next
l.textChangingLabel.SetText(l.values[l.current])
l.updateValue(l.optionID, l.values[l.current])
currentValue := l.values[l.current]
if err := l.textChangingLabel.SetText(currentValue); err != nil {
fmt.Printf("could not change the label text to: %s\n", currentValue)
}
l.updateValue(l.optionID, currentValue)
}
type actionableElement interface {
@ -113,6 +121,7 @@ type actionableElement interface {
Trigger()
}
// NewEscapeMenu creates a new escape menu
func NewEscapeMenu(audioProvider d2interface.AudioProvider, term d2interface.Terminal) *EscapeMenu {
m := &EscapeMenu{
audioProvider: audioProvider,
@ -127,6 +136,7 @@ func NewEscapeMenu(audioProvider d2interface.AudioProvider, term d2interface.Ter
automapOptionsLayoutID: m.newAutomapOptionsLayout(),
configureControlsLayoutID: m.newConfigureControlsLayout(),
}
return m
}
@ -157,7 +167,7 @@ func (m *EscapeMenu) newSoundOptionsLayout() *layout {
m.addEnumLabel(l, optAudioHardwareAcceleration, "HARDWARE ACCELERATION", []string{"ON", "OFF"})
m.addEnumLabel(l, optAudioEnvEffects, "ENVIRONMENTAL EFFECTS", []string{"ON", "OFF"})
m.addEnumLabel(l, optAudioNpcSpeech, "NPC SPEECH", []string{"AUDIO AND TEXT", "AUDIO ONLY", "TEXT ONLY"})
m.addPreviousMenuLabel(l, optionsLayoutID)
m.addPreviousMenuLabel(l)
})
}
@ -170,7 +180,7 @@ func (m *EscapeMenu) newVideoOptionsLayout() *layout {
m.addEnumLabel(l, optVideoPerspective, "PERSPECTIVE", []string{"ON", "OFF"})
m.addEnumLabel(l, optVideoGamma, "GAMMA", []string{"TODO"})
m.addEnumLabel(l, optVideoContrast, "CONTRAST", []string{"TODO"})
m.addPreviousMenuLabel(l, optionsLayoutID)
m.addPreviousMenuLabel(l)
})
}
@ -182,14 +192,14 @@ func (m *EscapeMenu) newAutomapOptionsLayout() *layout {
m.addEnumLabel(l, optAutomapCenterWhenCleared, "CENTER WHEN CLEARED", []string{"YES", "NO"})
m.addEnumLabel(l, optAutomapShowParty, "SHOW PARTY", []string{"YES", "NO"})
m.addEnumLabel(l, optAutomapShowNames, "SHOW NAMES", []string{"YES", "NO"})
m.addPreviousMenuLabel(l, optionsLayoutID)
m.addPreviousMenuLabel(l)
})
}
func (m *EscapeMenu) newConfigureControlsLayout() *layout {
return m.wrapLayout(func(l *layout) {
m.addTitle(l, "CONFIGURE CONTROLS")
m.addPreviousMenuLabel(l, optionsLayoutID)
m.addPreviousMenuLabel(l)
})
}
@ -221,6 +231,7 @@ func (m *EscapeMenu) wrapLayout(fn func(*layout)) *layout {
m.rightPent = rightPent
wrapper.AddSpacerDynamic()
return &layout{
Layout: wrapper,
leftPent: leftPent,
@ -230,7 +241,11 @@ func (m *EscapeMenu) wrapLayout(fn func(*layout)) *layout {
}
func (m *EscapeMenu) addTitle(l *layout, text string) {
l.AddLabel(text, d2gui.FontStyle42Units)
_, err := l.AddLabel(text, d2gui.FontStyle42Units)
if err != nil {
fmt.Printf("could not add label: %s to the escape menu\n", text)
}
l.AddSpacerStatic(10, labelGutter)
}
@ -240,7 +255,9 @@ func (m *EscapeMenu) addBigSelectionLabel(l *layout, text string, targetLayout l
label.SetMouseClickHandler(func(_ d2input.MouseEvent) {
label.Trigger()
})
elID := len(l.actionableElements)
label.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
m.onHoverElement(elID)
})
@ -248,17 +265,20 @@ func (m *EscapeMenu) addBigSelectionLabel(l *layout, text string, targetLayout l
l.actionableElements = append(l.actionableElements, label)
}
func (m *EscapeMenu) addPreviousMenuLabel(l *layout, targetLayout layoutID) {
func (m *EscapeMenu) addPreviousMenuLabel(l *layout) {
l.AddSpacerStatic(10, labelGutter)
guiLabel, _ := l.AddLabel("PREVIOUS MENU", d2gui.FontStyle30Units)
label := &showLayoutLabel{Label: guiLabel, target: targetLayout, showLayout: m.showLayout}
label := &showLayoutLabel{Label: guiLabel, target: optionsLayoutID, showLayout: m.showLayout}
label.SetMouseClickHandler(func(_ d2input.MouseEvent) {
label.Trigger()
})
elID := len(l.actionableElements)
label.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
m.onHoverElement(elID)
})
l.actionableElements = append(l.actionableElements, label)
}
@ -266,8 +286,14 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
guiLayout := l.AddLayout(d2gui.PositionTypeHorizontal)
layout := &layout{Layout: guiLayout}
layout.SetSize(menuSize, 0)
layout.AddLabel(text, d2gui.FontStyle30Units)
_, err := layout.AddLabel(text, d2gui.FontStyle30Units)
if err != nil {
fmt.Printf("could not add label: %s to the escape menu\n", text)
}
elID := len(l.actionableElements)
layout.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
m.onHoverElement(elID)
})
@ -282,6 +308,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
playSound: m.playSound,
updateValue: m.onUpdateValue,
}
layout.SetMouseClickHandler(func(_ d2input.MouseEvent) {
label.Trigger()
})
@ -289,13 +316,13 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
l.actionableElements = append(l.actionableElements, label)
}
func (m *EscapeMenu) OnLoad() {
func (m *EscapeMenu) onLoad() {
m.selectSound, _ = m.audioProvider.LoadSoundEffect(d2resource.SFXCursorSelect)
}
func (m *EscapeMenu) OnEscKey() {
func (m *EscapeMenu) onEscKey() {
if !m.isOpen {
m.Open()
m.open()
return
}
@ -311,19 +338,16 @@ func (m *EscapeMenu) OnEscKey() {
return
}
m.Close()
m.close()
}
func (m *EscapeMenu) IsOpen() bool {
return m.isOpen
}
func (m *EscapeMenu) Close() {
func (m *EscapeMenu) close() {
m.isOpen = false
d2gui.SetLayout(nil)
}
func (m *EscapeMenu) Open() {
func (m *EscapeMenu) open() {
m.isOpen = true
m.setLayout(mainLayoutID)
}
@ -336,14 +360,15 @@ func (m *EscapeMenu) showLayout(id layoutID) {
m.playSound()
if id == noLayoutID {
m.Close()
m.close()
return
}
if id == saveLayoutID {
mainMenu := CreateMainMenu(m.audioProvider, m.terminal)
mainMenu.SetScreenMode(ScreenModeMainMenu)
mainMenu.setScreenMode(screenModeMainMenu)
d2screen.SetNextScreen(mainMenu)
return
}
@ -358,12 +383,10 @@ func (m *EscapeMenu) onHoverElement(id int) {
m.leftPent.SetPosition(x, y+10)
x, _ = m.rightPent.GetPosition()
m.rightPent.SetPosition(x, y+10)
return
}
func (m *EscapeMenu) onUpdateValue(optID optionID, value string) {
fmt.Println(fmt.Sprintf("updating value %d with %s", optID, value))
fmt.Printf("updating value %d with %s\n", optID, value)
}
func (m *EscapeMenu) setLayout(id layoutID) {
@ -379,6 +402,7 @@ func (m *EscapeMenu) onUpKey() {
if !m.isOpen {
return
}
if m.layouts[m.currentLayout].currentEl == 0 {
return
}
@ -390,6 +414,7 @@ func (m *EscapeMenu) onDownKey() {
if !m.isOpen {
return
}
if m.layouts[m.currentLayout].currentEl == len(m.layouts[m.currentLayout].actionableElements)-1 {
return
}
@ -401,13 +426,15 @@ func (m *EscapeMenu) onEnterKey() {
if !m.isOpen {
return
}
m.layouts[m.currentLayout].actionableElements[m.layouts[m.currentLayout].currentEl].Trigger()
}
// OnKeyDown defines the actions of the Escape Menu when a key is pressed
func (m *EscapeMenu) OnKeyDown(event d2input.KeyEvent) bool {
switch event.Key {
case d2input.KeyEscape:
m.OnEscKey()
m.onEscKey()
case d2input.KeyUp:
m.onUpKey()
case d2input.KeyDown:
@ -417,5 +444,6 @@ func (m *EscapeMenu) OnKeyDown(event d2input.KeyEvent) bool {
default:
return false
}
return false
return true
}

View File

@ -43,8 +43,9 @@ func CreateGame(audioProvider d2interface.AudioProvider, gameClient *d2client.Ga
audioProvider: audioProvider,
terminal: term,
}
result.escapeMenu.OnLoad()
result.escapeMenu.onLoad()
d2input.BindHandler(result.escapeMenu)
return result
}
@ -55,6 +56,7 @@ func (v *Game) OnLoad(loading d2screen.LoadingState) {
func (v *Game) OnUnload() error {
d2input.UnbindHandler(v.gameControls) // TODO: hack
v.gameClient.Close()
return nil
}
@ -77,7 +79,7 @@ func (v *Game) Render(screen d2interface.Surface) error {
var hideZoneTextAfterSeconds = 2.0
func (v *Game) Advance(tickTime float64) error {
if (v.escapeMenu != nil && !v.escapeMenu.IsOpen()) || len(v.gameClient.Players) != 1 {
if (v.escapeMenu != nil && !v.escapeMenu.isOpen) || len(v.gameClient.Players) != 1 {
v.gameClient.MapEngine.Advance(tickTime) // TODO: Hack
}
@ -101,6 +103,7 @@ func (v *Game) Advance(tickTime float64) error {
v.gameControls.ShowZoneChangeText()
v.gameControls.HideZoneChangeTextAfter(hideZoneTextAfterSeconds)
}
v.lastRegionType = tile.RegionType
}
}
@ -112,6 +115,7 @@ func (v *Game) Advance(tickTime float64) error {
if player.Id != v.gameClient.PlayerId {
continue
}
v.localPlayer = player
v.gameControls = d2player.NewGameControls(player, v.gameClient.MapEngine, v.mapRenderer, v, v.terminal)
v.gameControls.Load()
@ -126,6 +130,7 @@ func (v *Game) Advance(tickTime float64) error {
rx, ry := v.mapRenderer.WorldToOrtho(v.localPlayer.LocationX/5, v.localPlayer.LocationY/5)
v.mapRenderer.MoveCameraTo(rx, ry)
}
return nil
}

View File

@ -14,6 +14,7 @@ func CreateGuiTestMain() *GuiTestMain {
func (g *GuiTestMain) OnLoad(loading d2screen.LoadingState) {
layout := d2gui.CreateLayout(d2gui.PositionTypeHorizontal)
loading.Progress(0.3)
//
layoutLeft := layout.AddLayout(d2gui.PositionTypeVertical)

View File

@ -24,27 +24,27 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
type MainMenuScreenMode int
type mainMenuScreenMode int
const (
ScreenModeUnknown MainMenuScreenMode = iota
ScreenModeTrademark
ScreenModeMainMenu
ScreenModeMultiplayer
ScreenModeTcpIp
ScreenModeServerIp
screenModeUnknown mainMenuScreenMode = iota
screenModeTrademark
screenModeMainMenu
screenModeMultiplayer
screenModeTCPIP
screenModeServerIP
)
// MainMenu represents the main menu
type MainMenu struct {
tcpIpBackground *d2ui.Sprite
tcpIPBackground *d2ui.Sprite
trademarkBackground *d2ui.Sprite
background *d2ui.Sprite
diabloLogoLeft *d2ui.Sprite
diabloLogoRight *d2ui.Sprite
diabloLogoLeftBack *d2ui.Sprite
diabloLogoRightBack *d2ui.Sprite
serverIpBackground *d2ui.Sprite
serverIPBackground *d2ui.Sprite
singlePlayerButton d2ui.Button
multiplayerButton d2ui.Button
githubButton d2ui.Button
@ -52,22 +52,22 @@ type MainMenu struct {
creditsButton d2ui.Button
cinematicsButton d2ui.Button
mapTestButton d2ui.Button
networkTcpIpButton d2ui.Button
networkTCPIPButton d2ui.Button
networkCancelButton d2ui.Button
btnTcpIpCancel d2ui.Button
btnTcpIpHostGame d2ui.Button
btnTcpIpJoinGame d2ui.Button
btnServerIpCancel d2ui.Button
btnServerIpOk d2ui.Button
btnTCPIPCancel d2ui.Button
btnTCPIPHostGame d2ui.Button
btnTCPIPJoinGame d2ui.Button
btnServerIPCancel d2ui.Button
btnServerIPOk d2ui.Button
copyrightLabel d2ui.Label
copyrightLabel2 d2ui.Label
openDiabloLabel d2ui.Label
versionLabel d2ui.Label
commitLabel d2ui.Label
tcpIpOptionsLabel d2ui.Label
tcpIPOptionsLabel d2ui.Label
tcpJoinGameLabel d2ui.Label
tcpJoinGameEntry d2ui.TextBox
screenMode MainMenuScreenMode
screenMode mainMenuScreenMode
leftButtonHeld bool
audioProvider d2interface.AudioProvider
terminal d2interface.Terminal
@ -76,18 +76,59 @@ type MainMenu struct {
// CreateMainMenu creates an instance of MainMenu
func CreateMainMenu(audioProvider d2interface.AudioProvider, term d2interface.Terminal) *MainMenu {
return &MainMenu{
screenMode: ScreenModeUnknown,
screenMode: screenModeUnknown,
leftButtonHeld: true,
audioProvider: audioProvider,
terminal: term,
}
}
// Load is called to load the resources for the main menu
// OnLoad is called to load the resources for the main menu
func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
v.audioProvider.PlayBGM(d2resource.BGMTitle)
loading.Progress(0.2)
v.createLabels(loading)
v.loadBackgroundSprites()
v.createLogos(loading)
v.createButtons(loading)
v.tcpJoinGameEntry = d2ui.CreateTextbox()
v.tcpJoinGameEntry.SetPosition(318, 245)
v.tcpJoinGameEntry.SetFilter("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:")
d2ui.AddWidget(&v.tcpJoinGameEntry)
loading.Progress(0.9)
if v.screenMode == screenModeUnknown {
v.setScreenMode(screenModeTrademark)
} else {
v.setScreenMode(screenModeMainMenu)
}
if err := d2input.BindHandler(v); err != nil {
fmt.Println("failed to add main menu as event handler")
}
}
func (v *MainMenu) loadBackgroundSprites() {
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0)
animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
v.trademarkBackground, _ = d2ui.LoadSprite(animation)
v.trademarkBackground.SetPosition(0, 0)
animation, _ = d2asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
v.tcpIPBackground, _ = d2ui.LoadSprite(animation)
v.tcpIPBackground.SetPosition(0, 0)
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.serverIPBackground, _ = d2ui.LoadSprite(animation)
v.serverIPBackground.SetPosition(270, 175)
}
func (v *MainMenu) createLabels(loading d2screen.LoadingState) {
v.versionLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.versionLabel.Alignment = d2ui.LabelAlignRight
v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch)
@ -120,19 +161,22 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
v.openDiabloLabel.SetPosition(400, 580)
loading.Progress(0.5)
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0)
v.tcpIPOptionsLabel = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.tcpIPOptionsLabel.SetPosition(400, 23)
v.tcpIPOptionsLabel.Alignment = d2ui.LabelAlignCenter
v.tcpIPOptionsLabel.SetText("TCP/IP Options")
animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
v.trademarkBackground, _ = d2ui.LoadSprite(animation)
v.trademarkBackground.SetPosition(0, 0)
v.tcpJoinGameLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.tcpJoinGameLabel.Alignment = d2ui.LabelAlignCenter
v.tcpJoinGameLabel.SetText(d2common.CombineStrings(
d2common.SplitIntoLinesWithMaxWidth("Enter Host IP Address to Join Game", 23)))
animation, _ = d2asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
v.tcpIpBackground, _ = d2ui.LoadSprite(animation)
v.tcpIpBackground.SetPosition(0, 0)
v.tcpJoinGameLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.tcpJoinGameLabel.SetPosition(400, 190)
}
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
v.diabloLogoLeft, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeft.SetBlend(true)
v.diabloLogoLeft.PlayForward()
@ -152,7 +196,9 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
v.diabloLogoRightBack, _ = d2ui.LoadSprite(animation)
v.diabloLogoRightBack.SetPosition(400, 120)
}
func (v *MainMenu) createButtons(loading d2screen.LoadingState) {
v.exitDiabloButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "EXIT DIABLO II")
v.exitDiabloButton.SetPosition(264, 535)
v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() })
@ -173,11 +219,6 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
d2ui.AddWidget(&v.singlePlayerButton)
v.multiplayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MULTIPLAYER")
v.multiplayerButton.SetPosition(264, 330)
v.multiplayerButton.OnActivated(func() { v.onMultiplayerClicked() })
d2ui.AddWidget(&v.multiplayerButton)
v.githubButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "PROJECT WEBSITE")
v.githubButton.SetPosition(264, 400)
v.githubButton.OnActivated(func() { v.onGithubButtonClicked() })
@ -188,78 +229,69 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
v.mapTestButton.OnActivated(func() { v.onMapTestClicked() })
d2ui.AddWidget(&v.mapTestButton)
v.networkTcpIpButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "TCP/IP GAME")
v.networkTcpIpButton.SetPosition(264, 280)
v.networkTcpIpButton.OnActivated(func() { v.onNetworkTcpIpClicked() })
d2ui.AddWidget(&v.networkTcpIpButton)
v.btnTCPIPCancel = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("cancel"))
v.btnTCPIPCancel.SetPosition(33, 543)
v.btnTCPIPCancel.OnActivated(func() { v.onTCPIPCancelClicked() })
d2ui.AddWidget(&v.btnTCPIPCancel)
v.btnServerIPCancel = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, "CANCEL")
v.btnServerIPCancel.SetPosition(285, 305)
v.btnServerIPCancel.OnActivated(func() { v.onBtnTCPIPCancelClicked() })
d2ui.AddWidget(&v.btnServerIPCancel)
v.btnServerIPOk = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, "OK")
v.btnServerIPOk.SetPosition(420, 305)
v.btnServerIPOk.OnActivated(func() { v.onBtnTCPIPOkClicked() })
d2ui.AddWidget(&v.btnServerIPOk)
v.createMultiplayerMenuButtons()
loading.Progress(0.8)
}
func (v *MainMenu) createMultiplayerMenuButtons() {
v.multiplayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MULTIPLAYER")
v.multiplayerButton.SetPosition(264, 330)
v.multiplayerButton.OnActivated(func() { v.onMultiplayerClicked() })
d2ui.AddWidget(&v.multiplayerButton)
v.networkTCPIPButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "TCP/IP GAME")
v.networkTCPIPButton.SetPosition(264, 280)
v.networkTCPIPButton.OnActivated(func() { v.onNetworkTCPIPClicked() })
d2ui.AddWidget(&v.networkTCPIPButton)
v.networkCancelButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("cancel"))
v.networkCancelButton.SetPosition(264, 540)
v.networkCancelButton.OnActivated(func() { v.onNetworkCancelClicked() })
d2ui.AddWidget(&v.networkCancelButton)
v.btnTcpIpCancel = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("cancel"))
v.btnTcpIpCancel.SetPosition(33, 543)
v.btnTcpIpCancel.OnActivated(func() { v.onTcpIpCancelClicked() })
d2ui.AddWidget(&v.btnTcpIpCancel)
v.btnTCPIPHostGame = d2ui.CreateButton(d2ui.ButtonTypeWide, "HOST GAME")
v.btnTCPIPHostGame.SetPosition(264, 280)
v.btnTCPIPHostGame.OnActivated(func() { v.onTCPIPHostGameClicked() })
d2ui.AddWidget(&v.btnTCPIPHostGame)
v.btnTcpIpHostGame = d2ui.CreateButton(d2ui.ButtonTypeWide, "HOST GAME")
v.btnTcpIpHostGame.SetPosition(264, 280)
v.btnTcpIpHostGame.OnActivated(func() { v.onTcpIpHostGameClicked() })
d2ui.AddWidget(&v.btnTcpIpHostGame)
v.btnTcpIpJoinGame = d2ui.CreateButton(d2ui.ButtonTypeWide, "JOIN GAME")
v.btnTcpIpJoinGame.SetPosition(264, 320)
v.btnTcpIpJoinGame.OnActivated(func() { v.onTcpIpJoinGameClicked() })
d2ui.AddWidget(&v.btnTcpIpJoinGame)
loading.Progress(0.8)
v.tcpIpOptionsLabel = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.tcpIpOptionsLabel.SetPosition(400, 23)
v.tcpIpOptionsLabel.Alignment = d2ui.LabelAlignCenter
v.tcpIpOptionsLabel.SetText("TCP/IP Options")
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.serverIpBackground, _ = d2ui.LoadSprite(animation)
v.serverIpBackground.SetPosition(270, 175)
v.tcpJoinGameLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.tcpJoinGameLabel.Alignment = d2ui.LabelAlignCenter
v.tcpJoinGameLabel.SetText(d2common.CombineStrings(d2common.
SplitIntoLinesWithMaxWidth("Enter Host IP Address to Join Game", 23)))
v.tcpJoinGameLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.tcpJoinGameLabel.SetPosition(400, 190)
v.tcpJoinGameEntry = d2ui.CreateTextbox()
v.tcpJoinGameEntry.SetPosition(318, 245)
v.tcpJoinGameEntry.SetFilter("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:")
d2ui.AddWidget(&v.tcpJoinGameEntry)
loading.Progress(0.9)
v.btnServerIpCancel = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, "CANCEL")
v.btnServerIpCancel.SetPosition(285, 305)
v.btnServerIpCancel.OnActivated(func() { v.onBtnTcpIpCancelClicked() })
d2ui.AddWidget(&v.btnServerIpCancel)
v.btnServerIpOk = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, "OK")
v.btnServerIpOk.SetPosition(420, 305)
v.btnServerIpOk.OnActivated(func() { v.onBtnTcpIpOkClicked() })
d2ui.AddWidget(&v.btnServerIpOk)
if v.screenMode == ScreenModeUnknown {
v.SetScreenMode(ScreenModeTrademark)
} else {
v.SetScreenMode(ScreenModeMainMenu)
}
d2input.BindHandler(v)
v.btnTCPIPJoinGame = d2ui.CreateButton(d2ui.ButtonTypeWide, "JOIN GAME")
v.btnTCPIPJoinGame.SetPosition(264, 320)
v.btnTCPIPJoinGame.OnActivated(func() { v.onTCPIPJoinGameClicked() })
d2ui.AddWidget(&v.btnTCPIPJoinGame)
}
func (v *MainMenu) onMapTestClicked() {
d2screen.SetNextScreen(CreateMapEngineTest(0, 1, v.terminal))
}
func openbrowser(url string) {
func (v *MainMenu) onSinglePlayerClicked() {
// Go here only if existing characters are available to select
if d2player.HasGameStates() {
d2screen.SetNextScreen(CreateCharacterSelect(v.audioProvider, d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText(), v.terminal))
return
}
d2screen.SetNextScreen(CreateSelectHeroClass(v.audioProvider, d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText()))
}
func (v *MainMenu) onGithubButtonClicked() {
url := "https://www.github.com/OpenDiablo2/OpenDiablo2"
var err error
switch runtime.GOOS {
@ -272,23 +304,10 @@ func openbrowser(url string) {
default:
err = fmt.Errorf("unsupported platform")
}
if err != nil {
log.Fatal(err)
}
}
func (v *MainMenu) onSinglePlayerClicked() {
// Go here only if existing characters are available to select
if d2player.HasGameStates() {
d2screen.SetNextScreen(CreateCharacterSelect(v.audioProvider, d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText(), v.terminal))
return
}
d2screen.SetNextScreen(CreateSelectHeroClass(v.audioProvider, d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText()))
}
func (v *MainMenu) onGithubButtonClicked() {
openbrowser("https://www.github.com/OpenDiablo2/OpenDiablo2")
}
func (v *MainMenu) onExitButtonClicked() {
@ -301,40 +320,78 @@ func (v *MainMenu) onCreditsButtonClicked() {
// Render renders the main menu
func (v *MainMenu) Render(screen d2interface.Surface) error {
if err := v.renderBackgrounds(screen); err != nil {
return err
}
if err := v.renderLogos(screen); err != nil {
return err
}
if err := v.renderLabels(screen); err != nil {
return err
}
return nil
}
func (v *MainMenu) renderBackgrounds(screen d2interface.Surface) error {
switch v.screenMode {
case ScreenModeTrademark:
v.trademarkBackground.RenderSegmented(screen, 4, 3, 0)
case ScreenModeServerIp:
fallthrough
case ScreenModeTcpIp:
v.tcpIpBackground.RenderSegmented(screen, 4, 3, 0)
case screenModeTrademark:
if err := v.trademarkBackground.RenderSegmented(screen, 4, 3, 0); err != nil {
return err
}
case screenModeServerIP:
if err := v.serverIPBackground.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
}
case screenModeTCPIP:
if err := v.tcpIPBackground.RenderSegmented(screen, 4, 3, 0); err != nil {
return err
}
default:
v.background.RenderSegmented(screen, 4, 3, 0)
if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil {
return err
}
}
return nil
}
func (v *MainMenu) renderLogos(screen d2interface.Surface) error {
switch v.screenMode {
case ScreenModeTrademark:
fallthrough
case ScreenModeMainMenu:
fallthrough
case ScreenModeMultiplayer:
v.diabloLogoLeftBack.Render(screen)
v.diabloLogoRightBack.Render(screen)
v.diabloLogoLeft.Render(screen)
v.diabloLogoRight.Render(screen)
case screenModeTrademark, screenModeMainMenu, screenModeMultiplayer:
if err := v.diabloLogoLeftBack.Render(screen); err != nil {
return err
}
if err := v.diabloLogoRightBack.Render(screen); err != nil {
return err
}
if err := v.diabloLogoLeft.Render(screen); err != nil {
return err
}
if err := v.diabloLogoRight.Render(screen); err != nil {
return err
}
}
return nil
}
func (v *MainMenu) renderLabels(screen d2interface.Surface) error {
switch v.screenMode {
case ScreenModeServerIp:
v.tcpIpOptionsLabel.Render(screen)
v.serverIpBackground.RenderSegmented(screen, 2, 1, 0)
case screenModeServerIP:
v.tcpIPOptionsLabel.Render(screen)
v.tcpJoinGameLabel.Render(screen)
case ScreenModeTcpIp:
v.tcpIpOptionsLabel.Render(screen)
case ScreenModeTrademark:
case screenModeTCPIP:
v.tcpIPOptionsLabel.Render(screen)
case screenModeTrademark:
v.copyrightLabel.Render(screen)
v.copyrightLabel2.Render(screen)
case ScreenModeMainMenu:
case screenModeMainMenu:
v.openDiabloLabel.Render(screen)
v.versionLabel.Render(screen)
v.commitLabel.Render(screen)
@ -343,37 +400,47 @@ func (v *MainMenu) Render(screen d2interface.Surface) error {
return nil
}
// Update runs the update logic on the main menu
// Advance runs the update logic on the main menu
func (v *MainMenu) Advance(tickTime float64) error {
switch v.screenMode {
case ScreenModeMainMenu:
fallthrough
case ScreenModeTrademark:
fallthrough
case ScreenModeMultiplayer:
v.diabloLogoLeftBack.Advance(tickTime)
v.diabloLogoRightBack.Advance(tickTime)
v.diabloLogoLeft.Advance(tickTime)
v.diabloLogoRight.Advance(tickTime)
case screenModeMainMenu, screenModeTrademark, screenModeMultiplayer:
if err := v.diabloLogoLeftBack.Advance(tickTime); err != nil {
return err
}
if err := v.diabloLogoRightBack.Advance(tickTime); err != nil {
return err
}
if err := v.diabloLogoLeft.Advance(tickTime); err != nil {
return err
}
if err := v.diabloLogoRight.Advance(tickTime); err != nil {
return err
}
}
return nil
}
// OnMouseButtonDown is called when a mouse button is clicked
func (v *MainMenu) OnMouseButtonDown(event d2input.MouseEvent) bool {
if v.screenMode == ScreenModeTrademark && event.Button == d2input.MouseButtonLeft {
v.SetScreenMode(ScreenModeMainMenu)
if v.screenMode == screenModeTrademark && event.Button == d2input.MouseButtonLeft {
v.setScreenMode(screenModeMainMenu)
return true
}
return false
}
func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
func (v *MainMenu) setScreenMode(screenMode mainMenuScreenMode) {
v.screenMode = screenMode
isMainMenu := screenMode == ScreenModeMainMenu
isMultiplayer := screenMode == ScreenModeMultiplayer
isTcpIp := screenMode == ScreenModeTcpIp
isServerIp := screenMode == ScreenModeServerIp
isMainMenu := screenMode == screenModeMainMenu
isMultiplayer := screenMode == screenModeMultiplayer
isTCPIP := screenMode == screenModeTCPIP
isServerIP := screenMode == screenModeServerIP
v.exitDiabloButton.SetVisible(isMainMenu)
v.creditsButton.SetVisible(isMainMenu)
v.cinematicsButton.SetVisible(isMainMenu)
@ -381,47 +448,49 @@ func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
v.githubButton.SetVisible(isMainMenu)
v.mapTestButton.SetVisible(isMainMenu)
v.multiplayerButton.SetVisible(isMainMenu)
v.networkTcpIpButton.SetVisible(isMultiplayer)
v.networkTCPIPButton.SetVisible(isMultiplayer)
v.networkCancelButton.SetVisible(isMultiplayer)
v.btnTcpIpCancel.SetVisible(isTcpIp)
v.btnTcpIpHostGame.SetVisible(isTcpIp)
v.btnTcpIpJoinGame.SetVisible(isTcpIp)
v.tcpJoinGameEntry.SetVisible(isServerIp)
if isServerIp {
v.btnTCPIPCancel.SetVisible(isTCPIP)
v.btnTCPIPHostGame.SetVisible(isTCPIP)
v.btnTCPIPJoinGame.SetVisible(isTCPIP)
v.tcpJoinGameEntry.SetVisible(isServerIP)
if isServerIP {
v.tcpJoinGameEntry.Activate()
}
v.btnServerIpOk.SetVisible(isServerIp)
v.btnServerIpCancel.SetVisible(isServerIp)
v.btnServerIPOk.SetVisible(isServerIP)
v.btnServerIPCancel.SetVisible(isServerIP)
}
func (v *MainMenu) onNetworkCancelClicked() {
v.SetScreenMode(ScreenModeMainMenu)
v.setScreenMode(screenModeMainMenu)
}
func (v *MainMenu) onMultiplayerClicked() {
v.SetScreenMode(ScreenModeMultiplayer)
v.setScreenMode(screenModeMultiplayer)
}
func (v *MainMenu) onNetworkTcpIpClicked() {
v.SetScreenMode(ScreenModeTcpIp)
func (v *MainMenu) onNetworkTCPIPClicked() {
v.setScreenMode(screenModeTCPIP)
}
func (v *MainMenu) onTcpIpCancelClicked() {
v.SetScreenMode(ScreenModeMultiplayer)
func (v *MainMenu) onTCPIPCancelClicked() {
v.setScreenMode(screenModeMultiplayer)
}
func (v *MainMenu) onTcpIpHostGameClicked() {
func (v *MainMenu) onTCPIPHostGameClicked() {
d2screen.SetNextScreen(CreateCharacterSelect(v.audioProvider, d2clientconnectiontype.LANServer, "", v.terminal))
}
func (v *MainMenu) onTcpIpJoinGameClicked() {
v.SetScreenMode(ScreenModeServerIp)
func (v *MainMenu) onTCPIPJoinGameClicked() {
v.setScreenMode(screenModeServerIP)
}
func (v *MainMenu) onBtnTcpIpCancelClicked() {
v.SetScreenMode(ScreenModeTcpIp)
func (v *MainMenu) onBtnTCPIPCancelClicked() {
v.setScreenMode(screenModeTCPIP)
}
func (v *MainMenu) onBtnTcpIpOkClicked() {
func (v *MainMenu) onBtnTCPIPOkClicked() {
d2screen.SetNextScreen(CreateCharacterSelect(v.audioProvider, d2clientconnectiontype.LANClient, v.tcpJoinGameEntry.GetText(), v.terminal))
}

View File

@ -1,6 +1,7 @@
package d2gamescreen
import (
"fmt"
"log"
"os"
"time"
@ -17,15 +18,15 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
)
type RegionSpec struct {
type regionSpec struct {
regionType d2enum.RegionIdType
startPresetIndex int
endPresetIndex int
extra []int
}
var regions = []RegionSpec{
//Act I
var regions = []regionSpec{
// Act I
{d2enum.RegionAct1Town, 1, 3, []int{}},
{d2enum.RegionAct1Wilderness, 4, 52, []int{
108,
@ -41,7 +42,7 @@ var regions = []RegionSpec{
{d2enum.RegionAct1Catacombs, 258, 299, []int{}},
{d2enum.RegionAct1Tristram, 300, 300, []int{}},
//Act II
// Act II
{d2enum.RegionAct2Town, 301, 301, []int{}},
{d2enum.RegionAct2Sewer, 302, 352, []int{}},
{d2enum.RegionAct2Harem, 353, 357, []int{}},
@ -51,24 +52,24 @@ var regions = []RegionSpec{
{d2enum.RegionAct2Lair, 482, 509, []int{}},
{d2enum.RegionAct2Arcane, 510, 528, []int{}},
//Act III
// Act III
{d2enum.RegionAct3Town, 529, 529, []int{}},
{d2enum.RegionAct3Jungle, 530, 604, []int{}},
{d2enum.RegionAct3Kurast, 605, 658, []int{
748, 749, 750, 751, 752, 753, 754,
755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796,
//yeah, i know =(
748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769,
770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791,
792, 793, 794, 795, 796,
}},
{d2enum.RegionAct3Spider, 659, 664, []int{}},
{d2enum.RegionAct3Dungeon, 665, 704, []int{}},
{d2enum.RegionAct3Sewer, 705, 747, []int{}},
//Act IV
// Act IV
{d2enum.RegionAct4Town, 797, 798, []int{}},
{d2enum.RegionAct4Mesa, 799, 835, []int{}},
{d2enum.RegionAct4Lava, 836, 862, []int{}},
//Act V -- broken or wrong order
// Act V -- broken or wrong order
{d2enum.RegonAct5Town, 863, 864, []int{}},
{d2enum.RegionAct5Siege, 865, 879, []int{}},
{d2enum.RegionAct5Barricade, 880, 1002, []int{}},
@ -88,37 +89,42 @@ type MapEngineTest struct {
currentRegion int
levelPreset int
fileIndex int
regionSpec RegionSpec
regionSpec regionSpec
filesCount int
debugVisLevel int
}
func CreateMapEngineTest(currentRegion int, levelPreset int, term d2interface.Terminal) *MapEngineTest {
// CreateMapEngineTest creates the Map Engine Test screen and returns a pointer to it
func CreateMapEngineTest(currentRegion, levelPreset int, term d2interface.Terminal) *MapEngineTest {
result := &MapEngineTest{
currentRegion: currentRegion,
levelPreset: levelPreset,
fileIndex: 0,
regionSpec: RegionSpec{},
regionSpec: regionSpec{},
filesCount: 0,
terminal: term,
}
result.gameState = d2player.CreateTestGameState()
return result
}
func (met *MapEngineTest) LoadRegionByIndex(n int, levelPreset, fileIndex int) {
func (met *MapEngineTest) loadRegionByIndex(n int, levelPreset, fileIndex int) {
log.Printf("Loaded region: Type(%d) LevelPreset(%d) FileIndex(%d)", n, levelPreset, fileIndex)
d2maprenderer.InvalidateImageCache()
for _, spec := range regions {
if spec.regionType == d2enum.RegionIdType(n) {
met.regionSpec = spec
inExtra := false
for _, e := range spec.extra {
if e == levelPreset {
inExtra = true
break
}
}
if !inExtra {
if levelPreset < spec.startPresetIndex {
levelPreset = spec.startPresetIndex
@ -128,6 +134,7 @@ func (met *MapEngineTest) LoadRegionByIndex(n int, levelPreset, fileIndex int) {
levelPreset = spec.endPresetIndex
}
}
met.levelPreset = levelPreset
}
}
@ -141,25 +148,39 @@ func (met *MapEngineTest) LoadRegionByIndex(n int, levelPreset, fileIndex int) {
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex, true)
met.mapEngine.RegenerateWalkPaths()
}
met.mapRenderer.SetMapEngine(met.mapEngine)
met.mapRenderer.MoveCameraTo(met.mapRenderer.WorldToOrtho(met.mapEngine.GetCenterPosition()))
}
// OnLoad loads the resources for the Map Engine Test screen
func (met *MapEngineTest) OnLoad(loading d2screen.LoadingState) {
d2input.BindHandler(met)
if err := d2input.BindHandler(met); err != nil {
fmt.Printf("could not add MapEngineTest as event handler")
}
loading.Progress(0.2)
met.mapEngine = d2mapengine.CreateMapEngine()
loading.Progress(0.5)
met.mapRenderer = d2maprenderer.CreateMapRenderer(met.mapEngine, met.terminal)
loading.Progress(0.7)
met.LoadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
met.loadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
}
// OnUnload releases the resources for the Map Engine Test screen
func (met *MapEngineTest) OnUnload() error {
d2input.UnbindHandler(met)
if err := d2input.UnbindHandler(met); err != nil {
return err
}
return nil
}
// Render renders the Map Engine Test screen
func (met *MapEngineTest) Render(screen d2interface.Surface) error {
met.mapRenderer.Render(screen)
@ -260,12 +281,15 @@ func (met *MapEngineTest) Render(screen d2interface.Surface) error {
return nil
}
// Advance runs the update logic on the Map Engine Test screen
func (met *MapEngineTest) Advance(tickTime float64) error {
met.mapEngine.Advance(tickTime)
met.mapRenderer.Advance(tickTime)
return nil
}
// OnKeyRepeat is called to handle repeated key presses
func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool {
var moveSpeed float64 = 8
if event.KeyMod == d2input.KeyModShift {
@ -295,6 +319,7 @@ func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool {
return false
}
// OnKeyDown defines the actions of the Map Engine Test screen when a key is pressed
func (met *MapEngineTest) OnKeyDown(event d2input.KeyEvent) bool {
if event.Key == d2input.KeyEscape {
os.Exit(0)
@ -302,14 +327,14 @@ func (met *MapEngineTest) OnKeyDown(event d2input.KeyEvent) bool {
}
if event.Key == d2input.KeyN {
if event.KeyMod == d2input.KeyModControl {
//met.fileIndex = increment(met.fileIndex, 0, met.filesCount-1)
switch event.KeyMod {
case d2input.KeyModControl:
met.fileIndex++
d2screen.SetNextScreen(met)
} else if event.KeyMod == d2input.KeyModShift {
case d2input.KeyModShift:
met.levelPreset = increment(met.levelPreset, met.regionSpec.startPresetIndex, met.regionSpec.endPresetIndex)
d2screen.SetNextScreen(met)
} else {
default:
met.currentRegion = increment(met.currentRegion, 0, len(regions))
d2screen.SetNextScreen(met)
}
@ -318,14 +343,14 @@ func (met *MapEngineTest) OnKeyDown(event d2input.KeyEvent) bool {
}
if event.Key == d2input.KeyP {
if event.KeyMod == d2input.KeyModControl {
//met.fileIndex = decrement(met.fileIndex, 0, met.filesCount-1)
switch event.KeyMod {
case d2input.KeyModControl:
met.fileIndex--
d2screen.SetNextScreen(met)
} else if event.KeyMod == d2input.KeyModShift {
case d2input.KeyModShift:
met.levelPreset = decrement(met.levelPreset, met.regionSpec.startPresetIndex, met.regionSpec.endPresetIndex)
d2screen.SetNextScreen(met)
} else {
default:
met.currentRegion = decrement(met.currentRegion, 0, len(regions))
d2screen.SetNextScreen(met)
}
@ -341,6 +366,7 @@ func increment(v, min, max int) int {
if v > max {
return min
}
return v
}
@ -349,5 +375,6 @@ func decrement(v, min, max int) int {
if v < min {
return max
}
return v
}

View File

@ -80,6 +80,7 @@ func CreateSelectHeroClass(audioProvider d2interface.AudioProvider,
connectionHost: connectionHost,
audioProvider: audioProvider,
}
return result
}