308 lines
7.9 KiB
Go
308 lines
7.9 KiB
Go
package ordoor
|
|
|
|
import (
|
|
"log"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/ui"
|
|
)
|
|
|
|
func try(result error, into *error) {
|
|
if *into == nil {
|
|
*into = result
|
|
}
|
|
}
|
|
|
|
// These are UI interfaces covering the game entrypoint
|
|
|
|
func (o *Ordoor) mainDriver() (*ui.Driver, error) {
|
|
// Start in the "main" menu
|
|
main, err := o.buildDriver("main")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newGame, err := o.newGameDriver(main)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
loadGame, err := o.loadGameDriver(main)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
options, err := o.optionsDriver(main)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: clicking these buttons should load other interfaces
|
|
try(main.OnClick("2.1", func() { o.driver = newGame }), &err) // New game
|
|
try(main.OnClick("2.2", func() { o.driver = loadGame }), &err) // Load game
|
|
try(main.SetFreeze("2.3", true), &err) // Multiplayer - disable for now
|
|
try(main.OnClick("2.4", func() { o.driver = options }), &err) // Options
|
|
try(main.OnClick("2.5", func() { o.nextState = StateExit }), &err) // Quit
|
|
|
|
return main, err
|
|
}
|
|
|
|
func (o *Ordoor) newGameDriver(main *ui.Driver) (*ui.Driver, error) {
|
|
newGame, err := o.buildDriver("newgame")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
levelPly, err := o.levelPlyDriver(newGame)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
singles, err := o.singlesDriver(newGame)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
randomMap, err := o.randomMapDriver(newGame)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
try(newGame.OnClick("2.1", func() { o.driver = levelPly }), &err) // New campaign button
|
|
try(newGame.OnClick("2.2", func() { o.driver = singles }), &err) // Single scenario button
|
|
try(newGame.OnClick("2.3", func() { o.driver = randomMap }), &err) // Random scenario button
|
|
try(newGame.OnClick("2.4", func() { o.driver = main }), &err) // Back button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newGame, nil
|
|
}
|
|
|
|
func (o *Ordoor) loadGameDriver(main *ui.Driver) (*ui.Driver, error) {
|
|
loadGame, err := o.buildDriver("loadgame")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
try(loadGame.OnClick("3.3", func() { o.driver = main }), &err) // Cancel button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return loadGame, nil
|
|
}
|
|
|
|
// Options needs to know how to go back to main
|
|
func (o *Ordoor) optionsDriver(main *ui.Driver) (*ui.Driver, error) {
|
|
options, err := o.buildDriver("options")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
kbd, err := o.keyboardDriver(options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := o.configIntoOptions(options); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
h3Slider := map[int]int{1: 8, 2: 56, 3: 110, 4: 120}
|
|
v10Slider := map[int]int{
|
|
0: 0,
|
|
10: 9, 20: 18, 30: 27, 40: 36, 50: 45,
|
|
60: 54, 70: 63, 80: 72, 90: 81, 100: 90,
|
|
}
|
|
h9Slider := map[int]int{
|
|
0: 0,
|
|
10: 10, 20: 20, 30: 30, 40: 40,
|
|
50: 50, 60: 60, 70: 70, 80: 80,
|
|
}
|
|
|
|
try(options.OnClick("2.8", func() { o.driver = kbd }), &err) // Keyboard settings button
|
|
|
|
try(options.ConfigureSlider("2.9", h3Slider), &err) // Resolution slider
|
|
try(options.ConfigureSlider("2.10", v10Slider), &err) // Music volume slider
|
|
try(options.ConfigureSlider("2.11", v10Slider), &err) // SFX volume slider
|
|
try(options.OnClick("2.12", acceptOptionsFn(o, main, options)), &err)
|
|
// 13...23 are "hypertext"
|
|
try(options.OnClick("2.24", cancelOptionsFn(o, main, options)), &err)
|
|
try(options.ConfigureSlider("2.26", h9Slider), &err) // Unit speed slider
|
|
try(options.ConfigureSlider("2.27", h9Slider), &err) // Animation speed slider
|
|
// Sample of unit speed animation is 2,28
|
|
// Sample of effect speed animation is 2,29
|
|
|
|
// 30...35 are "hypertext"
|
|
|
|
return options, err
|
|
}
|
|
|
|
// "Level of play menu when starting a new campaign
|
|
func (o *Ordoor) levelPlyDriver(newGame *ui.Driver) (*ui.Driver, error) {
|
|
levelPly, err := o.buildDriver("levelply")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
try(levelPly.OnClick("2.5", func() { o.driver = newGame }), &err) // Back button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return levelPly, nil
|
|
}
|
|
|
|
func (o *Ordoor) singlesDriver(newGame *ui.Driver) (*ui.Driver, error) {
|
|
singles, err := o.buildDriver("singles")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
try(singles.OnClick("4.11", func() { o.driver = newGame }), &err) // Back button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return singles, nil
|
|
}
|
|
|
|
func (o *Ordoor) randomMapDriver(newGame *ui.Driver) (*ui.Driver, error) {
|
|
randomMap, err := o.buildDriver("randommap")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
try(randomMap.OnClick("2.19", func() { o.driver = newGame }), &err) // Back button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return randomMap, nil
|
|
}
|
|
|
|
func (o *Ordoor) keyboardDriver(options *ui.Driver) (*ui.Driver, error) {
|
|
kbd, err := o.buildDriver("keyboard")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: implement keybindings save/load behaviour
|
|
try(kbd.OnClick("3.1", func() { o.driver = options }), &err) // Done button
|
|
try(kbd.OnClick("3.2", func() { o.driver = options }), &err) // Cancel button
|
|
try(kbd.OnClick("3.4", func() {}), &err) // Reset to defaults button
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return kbd, nil
|
|
}
|
|
|
|
// FIXME: exiting is a bit OTT. Perhaps display "save failed"?
|
|
func acceptOptionsFn(o *Ordoor, main, options *ui.Driver) func() {
|
|
return func() {
|
|
if err := o.optionsIntoConfig(options); err != nil {
|
|
log.Printf("Saving options to config failed: %v", err)
|
|
o.nextState = StateExit
|
|
} else {
|
|
o.driver = main
|
|
}
|
|
}
|
|
}
|
|
|
|
// FIXME: again, exiting is OTT. We're just resetting the state of
|
|
// the interface to the values in config.
|
|
func cancelOptionsFn(o *Ordoor, main, options *ui.Driver) func() {
|
|
return func() {
|
|
if err := o.configIntoOptions(options); err != nil {
|
|
log.Printf("Saving options to config failed: %v", err)
|
|
o.nextState = StateExit
|
|
} else {
|
|
o.driver = main
|
|
}
|
|
}
|
|
}
|
|
|
|
func (o *Ordoor) configIntoOptions(options *ui.Driver) error {
|
|
cfg := &o.config.Options
|
|
var err error
|
|
|
|
try(options.SetValueBool("2.1", cfg.PlayMovies), &err)
|
|
try(options.SetValueBool("2.1", cfg.Animations), &err)
|
|
try(options.SetValueBool("2.3", cfg.PlayMusic), &err)
|
|
try(options.SetValueBool("2.4", cfg.CombatVoices), &err)
|
|
try(options.SetValueBool("2.5", cfg.ShowGrid), &err)
|
|
try(options.SetValueBool("2.6", cfg.ShowPaths), &err)
|
|
try(options.SetValueBool("2.7", cfg.PointSaving), &err)
|
|
try(options.SetValueInt("2.9", cfg.ResolutionIndex()), &err)
|
|
try(options.SetValueInt("2.10", cfg.MusicVolume), &err)
|
|
try(options.SetValueInt("2.11", cfg.SFXVolume), &err)
|
|
try(options.SetValueBool("2.25", cfg.AutoCutLevel), &err)
|
|
try(options.SetValueInt("2.26", cfg.UnitSpeed), &err)
|
|
try(options.SetValueInt("2.27", cfg.AnimSpeed), &err)
|
|
|
|
return err
|
|
}
|
|
|
|
func (o *Ordoor) optionsIntoConfig(options *ui.Driver) error {
|
|
cfg := &o.config.Options
|
|
var resIdx int // needs handling manually
|
|
var err error
|
|
|
|
try(options.ValueBool("2.1", &cfg.PlayMovies), &err)
|
|
try(options.ValueBool("2.2", &cfg.Animations), &err)
|
|
try(options.ValueBool("2.3", &cfg.PlayMusic), &err)
|
|
try(options.ValueBool("2.4", &cfg.CombatVoices), &err)
|
|
try(options.ValueBool("2.5", &cfg.ShowGrid), &err)
|
|
try(options.ValueBool("2.6", &cfg.ShowPaths), &err)
|
|
try(options.ValueBool("2.7", &cfg.PointSaving), &err)
|
|
try(options.ValueInt("2.9", &resIdx), &err)
|
|
try(options.ValueInt("2.10", &cfg.MusicVolume), &err)
|
|
try(options.ValueInt("2.11", &cfg.SFXVolume), &err)
|
|
try(options.ValueBool("2.25", &cfg.AutoCutLevel), &err)
|
|
try(options.ValueInt("2.26", &cfg.UnitSpeed), &err)
|
|
try(options.ValueInt("2.27", &cfg.AnimSpeed), &err)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg.SetResolutionIndex(resIdx)
|
|
|
|
if err := o.config.Save(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: emit events, rather than just modifying state here
|
|
if o.music != nil && o.music.IsPlaying() != cfg.PlayMusic {
|
|
if cfg.PlayMusic {
|
|
o.music.Rewind()
|
|
o.music.Play()
|
|
} else {
|
|
o.music.Pause()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (o *Ordoor) buildDriver(name string) (*ui.Driver, error) {
|
|
menu, err := o.assets.Menu(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
driver, err := ui.NewDriver(menu)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return driver, nil
|
|
}
|