Wire up inventory select to ship state

Also mixed into this commit:

* Use returning drivers where possible
* Make the credits screen returnable via click
This commit is contained in:
2020-04-14 15:11:25 +01:00
parent 26c976353f
commit 2f65cd312a
11 changed files with 158 additions and 53 deletions

View File

@@ -4,11 +4,13 @@ func (f *Flow) linkBridge() {
// FIXME: sometimes these doors are frozen, depending on ship state, but we
// don't implement that yet.
f.onClick(bridge, "2.1", f.setDriver(briefing)) // Mission briefing clickable
f.onClick(bridge, "2.2", f.setDriver(choices)) // Options door hotspot
f.onClick(bridge, "2.4", f.playNextScenario(bridge)) // Enter combat door hotspot
f.setFreeze(bridge, "2.6", true) // TODO: Vehicle configure door hotspot
f.onClick(bridge, "2.8", f.setDriver(arrange)) // Squads configure door hotspot
f.onClick(bridge, "2.1", f.setReturningDriver(bridge, briefing)) // Mission briefing clickable
f.onClick(bridge, "2.2", f.setReturningDriver(bridge, choices)) // Options door hotspot
f.onClick(bridge, "2.4", f.playNextScenario(bridge)) // Enter combat door hotspot
f.setFreeze(bridge, "2.6", true) // TODO: Vehicle configure door hotspot
// FIXME: setReturningDriver would leave behind junk
f.onClick(bridge, "2.8", f.setDriver(arrange)) // Squads configure door hotspot.
// link children
f.linkBriefing()
@@ -21,19 +23,6 @@ func (f *Flow) linkBriefing() {
f.onClick(briefing, "3.1", f.setDriver(bridge))
}
func (f *Flow) linkChoices() {
f.onClick(choices, "2.1", f.setDriver(loadGame)) // Load another game button
f.onClick(choices, "2.2", f.setDriver(saveGame)) // Save this game button
f.onClick(choices, "2.3", f.setReturningDriver(choices, options)) // More options button
// FIXME: wipe out game state when this goes through
f.onClick(choices, "2.4", f.setDriver(main)) // Restart button
f.onClick(choices, "2.5", f.setDriver(credits)) // Credits button
f.onClick(choices, "2.6", f.setExit) // Quit button
f.onClick(choices, "2.7", f.setDriver(bridge)) // Back button
}
func (f *Flow) linkArrange() {
// FIXME: we should be operating on game data in here
f.onClick(arrange, "8.1", f.setDriver(bridge)) // Return to bridge ("cathedral")

20
internal/flow/choices.go Normal file
View File

@@ -0,0 +1,20 @@
package flow
func (f *Flow) linkChoices() {
f.onClick(choices, "2.1", f.setReturningDriver(choices, loadGame)) // Load another game button
f.onClick(choices, "2.2", f.setReturningDriver(choices, saveGame)) // Save this game button
f.onClick(choices, "2.3", f.setReturningDriver(choices, options)) // More options button
f.onClick(choices, "2.4", func() { // New Game button. FIXME: should ask about the emperor
f.ship.Reset() // Throws away in-progress game
f.reset()
})
f.onClick(choices, "2.5", f.setReturningDriver(choices, credits)) // Credits button
f.onClick(choices, "2.6", f.setExit) // Quit button. FIXME: should ask about the emperor
f.onClick(choices, "2.7", f.returnToLastDriver(choices)) // Back button
// loadGame is linked by main
f.linkSaveGame()
// options is linked by main
f.linkCredits()
}

8
internal/flow/credits.go Normal file
View File

@@ -0,0 +1,8 @@
package flow
func (f *Flow) linkCredits() {
// Clicking anywhere in credits should return us
f.onClick(credits, "1", f.returnToLastDriver(credits))
// TODO: lots of text
}

View File

@@ -86,15 +86,10 @@ func New(assets *assetstore.AssetStore, config *config.Config, ship *ship.Ship)
out.drivers[name] = driver
}
// Initial load of the config into the options UI
if err := out.configIntoOptions(); err != nil {
return nil, err
}
out.linkDrivers()
out.setDriverNow(main)
out.reset()
return out, nil
return out, out.exit
}
func buildDriver(assets *assetstore.AssetStore, name driverName) (*ui.Driver, error) {
@@ -164,11 +159,11 @@ func (f *Flow) Cursor() (*ebiten.Image, *ebiten.DrawImageOptions, error) {
func (f *Flow) linkDrivers() {
// linkMain
f.onClick(main, "2.1", f.setDriver(newGame)) // New game
f.onClick(main, "2.2", f.setDriver(loadGame)) // Load game
f.setFreeze(main, "2.3", true) // Multiplayer - disable for now
f.onClick(main, "2.4", f.setReturningDriver(main, options)) // Options
f.onClick(main, "2.5", f.setExit) // Quit
f.onClick(main, "2.1", f.setReturningDriver(main, newGame)) // New game
f.onClick(main, "2.2", f.setReturningDriver(main, loadGame)) // Load game
f.setFreeze(main, "2.3", true) // Multiplayer - disable for now
f.onClick(main, "2.4", f.setReturningDriver(main, options)) // Options
f.onClick(main, "2.5", f.setExit) // Quit
// Now link immediate children. They will link their children, and so on
f.linkNewGame()
@@ -217,6 +212,18 @@ func (f *Flow) setValueBool(driver driverName, id string, value bool) {
f.exit = f.drivers[driver].SetValueBool(id, value)
}
func (f *Flow) valueBool(driver driverName, id string) bool {
if f.exit != nil {
return false
}
var value bool
f.exit = f.drivers[driver].ValueBool(id, &value)
return value
}
func (f *Flow) playNextScenario(from driverName) func() {
return func() {
log.Printf("Loading scenario: %v", f.ship.NextScenario)
@@ -244,11 +251,26 @@ func (f *Flow) hideDialogue(driver driverName) func() {
return f.drivers[driver].HideDialogue
}
func (f *Flow) reset() {
if f.exit != nil {
return
}
f.setDriverNow(main) // Back to the main interface
// Wipe out any returns that may exist
f.returns = make(map[driverName]driverName)
// FIXME: these should really happen via data binding.
f.resetLevelPlyInventorySelect()
f.exit = f.configIntoOptions()
}
func (f *Flow) setExit() {
f.exit = ErrExit
}
// TODO: convert all to locators
func locator(d driverName, id string) string {
return fmt.Sprintf("%v:%v", strings.ToLower(string(d)), id)
func locator(driver driverName, id string) string {
return fmt.Sprintf("%v:%v", strings.ToLower(string(driver)), id)
}

View File

@@ -2,5 +2,5 @@ package flow
func (f *Flow) linkLoadGame() {
// Load game
f.onClick(loadGame, "3.3", f.setDriver(main)) // Cancel button
f.onClick(loadGame, "3.3", f.returnToLastDriver(loadGame)) // Cancel button
}

View File

@@ -1,36 +1,68 @@
package flow
import (
"code.ur.gs/lupine/ordoor/internal/ship"
)
func (f *Flow) linkNewGame() {
// New game
f.onClick(newGame, "2.1", f.setDriver(levelPly)) // New campaign button
f.onClick(newGame, "2.2", f.setDriver(singles)) // Single scenario button
f.onClick(newGame, "2.3", f.setDriver(randomMap)) // Random scenario button
f.onClick(newGame, "2.4", f.setDriver(main)) // Back button
f.onClick(newGame, "2.1", f.setReturningDriver(newGame, levelPly)) // New campaign button
f.onClick(newGame, "2.2", f.setReturningDriver(newGame, singles)) // Single scenario button
f.onClick(newGame, "2.3", f.setReturningDriver(newGame, randomMap)) // Random scenario button
f.onClick(newGame, "2.4", f.returnToLastDriver(newGame)) // Back button
f.linkLevelPly()
f.linkSingles()
f.linkRandomMap()
}
func (f *Flow) linkLevelPly() {
// We want the default difficulty level to be Veteran, not Hero.
func (f *Flow) resetLevelPlyInventorySelect() {
// FIXME: Make the radio button respect changes via setValue
resetLevel := func() {
f.setValueBool(levelPly, "2.1", false)
f.setValueBool(levelPly, "2.2", true)
for _, v := range []string{"2.1", "2.2", "2.3", "2.4"} {
f.setValueBool(levelPly, v, false)
}
resetLevel()
switch f.ship.Difficulty {
case ship.DifficultyLevelMarine:
f.setValueBool(levelPly, "2.1", true)
case ship.DifficultyLevelVeteran:
f.setValueBool(levelPly, "2.2", true)
case ship.DifficultyLevelHero:
f.setValueBool(levelPly, "2.3", true)
case ship.DifficultyLevelMighty:
f.setValueBool(levelPly, "2.4", true)
}
}
func (f *Flow) linkLevelPly() {
f.onClick(levelPly, "2.5", func() { // Back button
resetLevel()
f.setDriverNow(newGame)
f.resetLevelPlyInventorySelect() // FIXME: should use data binding
f.returnToLastDriverNow(levelPly)
})
// FIXME: we should select a savegame if Mighty Hero is selected here
// FIXME: we should show a movie here. Need an internal SMK player first
// FIXME: we should set up new game state here!
// FIXME: we should be able to read the difficulty level from the group
f.onClick(levelPly, "2.7", func() { // Select button
if f.valueBool(levelPly, "2.1") {
f.ship.Difficulty = ship.DifficultyLevelMarine
}
if f.valueBool(levelPly, "2.2") {
f.ship.Difficulty = ship.DifficultyLevelVeteran
}
if f.valueBool(levelPly, "2.3") {
f.ship.Difficulty = ship.DifficultyLevelHero
}
if f.valueBool(levelPly, "2.4") {
// FIXME: we should select a savegame. Mighty Hero disables manual saves.
f.ship.Difficulty = ship.DifficultyLevelMighty
}
f.ship.NextScenario = f.generic.CampaignMaps[0]
// FIXME: we should show a movie here. Need an internal SMK player first
f.setDriverNow(bridge)
})
@@ -39,9 +71,9 @@ func (f *Flow) linkLevelPly() {
}
func (f *Flow) linkSingles() {
f.onClick(singles, "4.11", f.setDriver(newGame)) // Back button
f.onClick(singles, "4.11", f.returnToLastDriver(singles)) // Back button
}
func (f *Flow) linkRandomMap() {
f.onClick(randomMap, "2.19", f.setDriver(newGame)) // Back button
f.onClick(randomMap, "2.19", f.returnToLastDriver(randomMap)) // Back button
}

View File

@@ -26,7 +26,7 @@ func (f *Flow) acceptOptions() {
log.Printf("Saving options to config failed: %v", err)
f.exit = err
} else {
f.setDriverNow(main)
f.returnToLastDriverNow(options)
}
}

View File

@@ -0,0 +1,10 @@
package flow
func (f *Flow) linkSaveGame() {
// Save game button is disabled unless a listbox item is selected
// 3.2 is a hypertext that should be displayed when 3.1 is disabled... but
// it has no DESC.
f.setFreeze(saveGame, "3.1", true)
f.onClick(saveGame, "3.1", func() {}) // TODO: Save Game button
f.onClick(saveGame, "3.3", f.returnToLastDriver(saveGame)) // Back button
}

View File

@@ -63,7 +63,7 @@ func Run(configFile string, overrideX, overrideY int) error {
ordoor := &Ordoor{
assets: assets,
config: cfg,
ship: &ship.Ship{},
ship: ship.New(),
}
x, y := cfg.Options.XRes, cfg.Options.YRes
@@ -95,7 +95,7 @@ func Run(configFile string, overrideX, overrideY int) error {
func (o *Ordoor) Run() error {
// FIXME: we're missing a screen about SSI here
if o.config.Options.PlayMovies {
o.PlayUnskippableVideo("LOGOS")
o.PlaySkippableVideo("LOGOS")
o.PlaySkippableVideo("movie1")
}

View File

@@ -1,8 +1,18 @@
package ship
type DifficultyLevel int
const (
DifficultyLevelMarine DifficultyLevel = 0
DifficultyLevelVeteran DifficultyLevel = 1
DifficultyLevelHero DifficultyLevel = 2
DifficultyLevelMighty DifficultyLevel = 3
)
// Ship encapsulates campaign state, including current location in the campaign,
// marines and their stats, supplies, etc.
type Ship struct {
Difficulty DifficultyLevel
NextScenario string
Squads []*Squad
@@ -68,3 +78,16 @@ type Honours struct {
PuritySeal bool
ImperialLaurel bool
}
func New() *Ship {
s := &Ship{}
s.Reset()
return s
}
func (s *Ship) Reset() {
*s = Ship{
Difficulty: DifficultyLevelVeteran, // Default difficulty level
}
}

View File

@@ -83,6 +83,7 @@ func (d *Driver) buildStatic(p *menus.Properties) (*noninteractive, *Widget, err
widget := &Widget{
Locator: ni.locator,
ownClickables: []clickable{ni}, // FIXME: credits background needs to be clickable
ownHoverables: []hoverable{ni},
ownPaintables: []paintable{ni},
}