Display MainGame.mnu and map in ordoor simultaneously
It's a complete mess for now - many things are out of place or shown when they shouldn't be - and we can't move around the game map. But, it's a good start.
This commit is contained in:
@@ -245,13 +245,14 @@ observed, suggesting structure. For instance, we have `24`, `240`, `241` and
|
||||
`2410`, but not `2411` or `2409`. Sometimes we have a comma-separated list,
|
||||
e.g.: `400,30,-1,5`.
|
||||
|
||||
A listing of currently-known values:
|
||||
A listing of some currently-known values:
|
||||
|
||||
| Value | Type |
|
||||
| ----- | ---------------- |
|
||||
| 0 | Static image |
|
||||
| 1 | Menu |
|
||||
| 3 | Button |
|
||||
| 45 | Thumb |
|
||||
| 50 | Invoke? Button? |
|
||||
| 61 | "Overlay" |
|
||||
| 70 | "Hypertext" |
|
||||
@@ -260,6 +261,13 @@ A listing of currently-known values:
|
||||
| 228 | Main menu button |
|
||||
| 232 | Slider |
|
||||
|
||||
Hypothesis: `MENUTYPE` and `SUBMENUTYPE` are actually distinct lists of values.
|
||||
So far, I've been treating them as the same thing, but, e.g., `MainGame.mnu` has
|
||||
a `MENUTYPE: 45` which is labelled "MAIN BACKGROUND", while `SUBMENUTYPE: 45`
|
||||
is tentatively labelled a "thumb" and used in text boxes. There are also a few
|
||||
cases where I've had to manually override the `MENUTYPE` because it coincides
|
||||
with `Button`.
|
||||
|
||||
### `ACTIVE`
|
||||
|
||||
There are only 4 values seen across all menus: `0`, `1`, `1,0`, `102` and `1,1`.
|
||||
|
@@ -4,15 +4,16 @@ 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()) // 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.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
|
||||
|
||||
// link children
|
||||
f.linkBriefing()
|
||||
f.linkChoices()
|
||||
f.linkMainGame()
|
||||
f.linkArrange()
|
||||
}
|
||||
|
||||
|
74
internal/flow/drivers.go
Normal file
74
internal/flow/drivers.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type driverName string
|
||||
|
||||
const (
|
||||
// Names of all the drivers
|
||||
main driverName = "Main"
|
||||
levelPly driverName = "LevelPly"
|
||||
singles driverName = "Singles"
|
||||
randomMap driverName = "RandomMap"
|
||||
newGame driverName = "NewGame"
|
||||
loadGame driverName = "LoadGame"
|
||||
options driverName = "Options"
|
||||
kbd driverName = "Keyboard"
|
||||
bridge driverName = "Bridge"
|
||||
briefing driverName = "Briefing"
|
||||
choices driverName = "Choices"
|
||||
saveGame driverName = "SaveGame"
|
||||
credits driverName = "Credits"
|
||||
arrange driverName = "Arrange"
|
||||
|
||||
configureUltEquip driverName = "Configure_UltEquip"
|
||||
configureVehiclesUltra driverName = "Configure_Vehicles_Ultra"
|
||||
|
||||
mainGame driverName = "MainGame"
|
||||
)
|
||||
|
||||
var (
|
||||
driverNames = []driverName{
|
||||
main, levelPly, singles, randomMap, newGame, loadGame, options, kbd,
|
||||
bridge, briefing, choices, saveGame, credits, arrange,
|
||||
configureUltEquip, configureVehiclesUltra,
|
||||
mainGame,
|
||||
}
|
||||
)
|
||||
|
||||
// from is the child menu, to is the parent
|
||||
func (f *Flow) returnToLastDriverNow(from driverName) error {
|
||||
to, ok := f.returns[from]
|
||||
if !ok {
|
||||
return fmt.Errorf("Couldn't work out where to return to from %v", from)
|
||||
}
|
||||
|
||||
delete(f.returns, from)
|
||||
|
||||
f.setDriverNow(to)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Flow) setDriver(name driverName) func() {
|
||||
return func() {
|
||||
f.setDriverNow(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flow) setDriverNow(name driverName) {
|
||||
f.current = f.drivers[name]
|
||||
}
|
||||
|
||||
// from is the parent menu, to is the child
|
||||
func (f *Flow) setReturningDriver(from, to driverName) func() {
|
||||
return func() {
|
||||
f.setReturningDriverNow(from, to)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flow) setReturningDriverNow(from, to driverName) {
|
||||
f.returns[to] = from
|
||||
f.setDriverNow(to)
|
||||
}
|
@@ -40,38 +40,9 @@ type Flow struct {
|
||||
exit error
|
||||
}
|
||||
|
||||
type driverName string
|
||||
|
||||
const (
|
||||
// Names of all the drivers
|
||||
main driverName = "Main"
|
||||
levelPly driverName = "LevelPly"
|
||||
singles driverName = "Singles"
|
||||
randomMap driverName = "RandomMap"
|
||||
newGame driverName = "NewGame"
|
||||
loadGame driverName = "LoadGame"
|
||||
options driverName = "Options"
|
||||
kbd driverName = "Keyboard"
|
||||
bridge driverName = "Bridge"
|
||||
briefing driverName = "Briefing"
|
||||
choices driverName = "Choices"
|
||||
saveGame driverName = "SaveGame"
|
||||
credits driverName = "Credits"
|
||||
arrange driverName = "Arrange"
|
||||
|
||||
configureUltEquip driverName = "Configure_UltEquip"
|
||||
configureVehiclesUltra driverName = "Configure_Vehicles_Ultra"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrExit = errors.New("exiting gracefully")
|
||||
|
||||
driverNames = []driverName{
|
||||
main, levelPly, singles, randomMap, newGame, loadGame, options, kbd,
|
||||
bridge, briefing, choices, saveGame, credits, arrange,
|
||||
configureUltEquip, configureVehiclesUltra,
|
||||
}
|
||||
|
||||
// Constants used for sliders
|
||||
|
||||
h3Slider = map[int]int{1: 8, 2: 56, 3: 110, 4: 120}
|
||||
@@ -245,25 +216,7 @@ func (f *Flow) setValueBool(driver driverName, id string, value bool) {
|
||||
f.exit = f.drivers[driver].SetValueBool(id, value)
|
||||
}
|
||||
|
||||
func (f *Flow) setDriver(name driverName) func() {
|
||||
return func() {
|
||||
f.setDriverNow(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flow) setDriverNow(name driverName) {
|
||||
f.current = f.drivers[name]
|
||||
}
|
||||
|
||||
// from is the parent menu, to is the child
|
||||
func (f *Flow) setReturningDriver(from, to driverName) func() {
|
||||
return func() {
|
||||
f.returns[to] = from
|
||||
f.setDriverNow(to)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flow) playNextScenario() func() {
|
||||
func (f *Flow) playNextScenario(from driverName) func() {
|
||||
return func() {
|
||||
log.Printf("Loading scenario: %v", f.ship.NextScenario)
|
||||
|
||||
@@ -275,24 +228,11 @@ func (f *Flow) playNextScenario() func() {
|
||||
return
|
||||
}
|
||||
|
||||
f.current = nil // TODO: show the UI for a scenario
|
||||
f.setReturningDriverNow(from, mainGame)
|
||||
f.scenario = scenario
|
||||
}
|
||||
}
|
||||
|
||||
// from is the child menu, to is the parent
|
||||
func (f *Flow) returnToLastDriverNow(from driverName) error {
|
||||
to, ok := f.returns[from]
|
||||
if !ok {
|
||||
return fmt.Errorf("Couldn't work out where to return to from %v", from)
|
||||
}
|
||||
|
||||
delete(f.returns, from)
|
||||
|
||||
f.setDriverNow(to)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Flow) setExit() {
|
||||
f.exit = ErrExit
|
||||
}
|
||||
|
55
internal/flow/main_game.go
Normal file
55
internal/flow/main_game.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package flow
|
||||
|
||||
// TODO: There are Chaos and Ultramarine versions of MainGame. Do we really want
|
||||
// to duplicate everything for both?
|
||||
|
||||
func (f *Flow) linkMainGame() {
|
||||
// 3: Action menu
|
||||
|
||||
// 4: Interface options menu
|
||||
f.onClick(mainGame, "4.1", f.setReturningDriver(mainGame, options)) // Options button
|
||||
// 4.2: Map button
|
||||
// 4.3: Mission objectives button
|
||||
// 4.4: Inventory
|
||||
// 4.5: Next man
|
||||
// 4.6: Next enemy
|
||||
// 4.7: Total enemy text
|
||||
|
||||
// 5: Holding menu
|
||||
// 6: View menu
|
||||
// 7: General character menu
|
||||
// 8: Character stats
|
||||
// 9: Visible enemy menu
|
||||
// 10: Friendly squad menu
|
||||
// 11: Psyker spell dialogue
|
||||
|
||||
// FIXME: lots and lots and lots of wiring up to do.
|
||||
// For now, just link all the exit buttons to go back to the bridge
|
||||
f.onClick(mainGame, "11.6", func() {
|
||||
f.scenario = nil
|
||||
f.returnToLastDriverNow(mainGame)
|
||||
})
|
||||
|
||||
// 12: Inventory dialogue
|
||||
f.onClick(mainGame, "12.21", func() {
|
||||
f.scenario = nil
|
||||
f.returnToLastDriverNow(mainGame)
|
||||
})
|
||||
|
||||
// 13: Exchange menu
|
||||
|
||||
f.onClick(mainGame, "13.1", func() {
|
||||
f.scenario = nil
|
||||
f.returnToLastDriverNow(mainGame)
|
||||
})
|
||||
|
||||
// 14: Map
|
||||
|
||||
// 15: Interface wing left
|
||||
// 16: Interface wing right
|
||||
// 17: Grenade dialogue
|
||||
// 18: Info dialogue
|
||||
// 19: Turn start dialogue
|
||||
// 20: Chat menu
|
||||
// 21: Chat list menu box
|
||||
}
|
@@ -65,11 +65,16 @@ var TextOverrides = map[string]string{
|
||||
|
||||
// FIXME: The menu is specified as type 2 (button) in these cases, which is
|
||||
// weird. Make it a menu for now.
|
||||
//
|
||||
// Hypothesis: MENUTYPE and SUBMENUTYPE are not equivalent?
|
||||
var TypeOverrides = map[string]MenuType{
|
||||
"levelply:2": TypeMenu,
|
||||
"savegame:2": TypeMenu,
|
||||
"loadgame:2": TypeMenu,
|
||||
|
||||
// "thumb" is not a background.
|
||||
"maingame:2": TypeStatic,
|
||||
|
||||
// ???
|
||||
"configure_ultequip:7.5": TypeListBoxUp,
|
||||
"configure_ultequip:7.6": TypeListBoxDown,
|
||||
|
@@ -327,7 +327,7 @@ func (d *Driver) Cursor() (*ebiten.Image, *ebiten.DrawImageOptions, error) {
|
||||
}
|
||||
|
||||
func (d *Driver) addRecord(record *menus.Record) error {
|
||||
//log.Printf("Adding record: %#+v", record)
|
||||
log.Printf("Adding record %v: %#+v", record.Locator(), record)
|
||||
children := record.Children
|
||||
|
||||
handler, ok := widgetBuilders[record.Type]
|
||||
|
@@ -45,6 +45,7 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
||||
var downBtn *menus.Record
|
||||
var thumb *menus.Record
|
||||
var items []*menus.Record
|
||||
var otherChildren []*menus.Record
|
||||
|
||||
for _, rec := range menu.Children {
|
||||
switch rec.Type {
|
||||
@@ -66,7 +67,8 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
||||
}
|
||||
thumb = rec
|
||||
default:
|
||||
return nil, fmt.Errorf("Unrecognised child in listbox menu: %v", rec.Locator())
|
||||
// e.g. maingame:18.12 includes a button that is not part of the box
|
||||
otherChildren = append(otherChildren, rec)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +82,21 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
elemUp, err := registerButton(d, upBtn, upBtn.SpriteId[0])
|
||||
upSprId := upBtn.SpriteId[0]
|
||||
if upSprId == -1 {
|
||||
upSprId = upBtn.Share
|
||||
}
|
||||
|
||||
elemUp, err := registerButton(d, upBtn, upSprId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
elemDown, err := registerButton(d, downBtn, downBtn.SpriteId[0])
|
||||
dnSprId := downBtn.SpriteId[0]
|
||||
if dnSprId == -1 {
|
||||
dnSprId = downBtn.Share
|
||||
}
|
||||
elemDown, err := registerButton(d, downBtn, dnSprId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +106,12 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
thumbImgSpr, err := d.menu.Sprite(thumb.SpriteId[0])
|
||||
thumbSprId := thumb.SpriteId[0]
|
||||
if thumbSprId == -1 {
|
||||
thumbSprId = thumb.Share
|
||||
}
|
||||
|
||||
thumbImgSpr, err := d.menu.Sprite(thumbSprId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -145,7 +161,7 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
||||
|
||||
element.refresh()
|
||||
|
||||
return nil, nil
|
||||
return otherChildren, nil
|
||||
}
|
||||
|
||||
func (l *listBox) SetStrings(to []string) {
|
||||
|
@@ -16,7 +16,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerBuilder(menus.TypeStatic, noChildren(registerStatic))
|
||||
registerBuilder(menus.TypeStatic, registerStatic) // MainGame has a hypertext child
|
||||
registerBuilder(menus.TypeHypertext, noChildren(registerHypertext))
|
||||
registerBuilder(menus.TypeOverlay, noChildren(registerOverlay))
|
||||
registerBuilder(menus.TypeAnimationSample, noChildren(registerAnimation))
|
||||
@@ -58,9 +58,9 @@ type animationHover struct {
|
||||
closing bool
|
||||
}
|
||||
|
||||
func registerStatic(d *Driver, r *menus.Record) error {
|
||||
func registerStatic(d *Driver, r *menus.Record) ([]*menus.Record, error) {
|
||||
_, err := registerNoninteractive(d, r)
|
||||
return err
|
||||
return r.Children, err
|
||||
}
|
||||
|
||||
func registerNoninteractive(d *Driver, r *menus.Record) (*noninteractive, error) {
|
||||
|
Reference in New Issue
Block a user