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,
|
`2410`, but not `2411` or `2409`. Sometimes we have a comma-separated list,
|
||||||
e.g.: `400,30,-1,5`.
|
e.g.: `400,30,-1,5`.
|
||||||
|
|
||||||
A listing of currently-known values:
|
A listing of some currently-known values:
|
||||||
|
|
||||||
| Value | Type |
|
| Value | Type |
|
||||||
| ----- | ---------------- |
|
| ----- | ---------------- |
|
||||||
| 0 | Static image |
|
| 0 | Static image |
|
||||||
| 1 | Menu |
|
| 1 | Menu |
|
||||||
| 3 | Button |
|
| 3 | Button |
|
||||||
|
| 45 | Thumb |
|
||||||
| 50 | Invoke? Button? |
|
| 50 | Invoke? Button? |
|
||||||
| 61 | "Overlay" |
|
| 61 | "Overlay" |
|
||||||
| 70 | "Hypertext" |
|
| 70 | "Hypertext" |
|
||||||
@@ -260,6 +261,13 @@ A listing of currently-known values:
|
|||||||
| 228 | Main menu button |
|
| 228 | Main menu button |
|
||||||
| 232 | Slider |
|
| 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`
|
### `ACTIVE`
|
||||||
|
|
||||||
There are only 4 values seen across all menus: `0`, `1`, `1,0`, `102` and `1,1`.
|
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
|
// FIXME: sometimes these doors are frozen, depending on ship state, but we
|
||||||
// don't implement that yet.
|
// don't implement that yet.
|
||||||
|
|
||||||
f.onClick(bridge, "2.1", f.setDriver(briefing)) // Mission briefing clickable
|
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.2", f.setDriver(choices)) // Options door hotspot
|
||||||
f.onClick(bridge, "2.4", f.playNextScenario()) // Enter combat 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.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.8", f.setDriver(arrange)) // Squads configure door hotspot
|
||||||
|
|
||||||
// link children
|
// link children
|
||||||
f.linkBriefing()
|
f.linkBriefing()
|
||||||
f.linkChoices()
|
f.linkChoices()
|
||||||
|
f.linkMainGame()
|
||||||
f.linkArrange()
|
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
|
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 (
|
var (
|
||||||
ErrExit = errors.New("exiting gracefully")
|
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
|
// Constants used for sliders
|
||||||
|
|
||||||
h3Slider = map[int]int{1: 8, 2: 56, 3: 110, 4: 120}
|
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)
|
f.exit = f.drivers[driver].SetValueBool(id, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flow) setDriver(name driverName) func() {
|
func (f *Flow) playNextScenario(from 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() {
|
|
||||||
return func() {
|
return func() {
|
||||||
log.Printf("Loading scenario: %v", f.ship.NextScenario)
|
log.Printf("Loading scenario: %v", f.ship.NextScenario)
|
||||||
|
|
||||||
@@ -275,24 +228,11 @@ func (f *Flow) playNextScenario() func() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.current = nil // TODO: show the UI for a scenario
|
f.setReturningDriverNow(from, mainGame)
|
||||||
f.scenario = scenario
|
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() {
|
func (f *Flow) setExit() {
|
||||||
f.exit = ErrExit
|
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
|
// FIXME: The menu is specified as type 2 (button) in these cases, which is
|
||||||
// weird. Make it a menu for now.
|
// weird. Make it a menu for now.
|
||||||
|
//
|
||||||
|
// Hypothesis: MENUTYPE and SUBMENUTYPE are not equivalent?
|
||||||
var TypeOverrides = map[string]MenuType{
|
var TypeOverrides = map[string]MenuType{
|
||||||
"levelply:2": TypeMenu,
|
"levelply:2": TypeMenu,
|
||||||
"savegame:2": TypeMenu,
|
"savegame:2": TypeMenu,
|
||||||
"loadgame:2": TypeMenu,
|
"loadgame:2": TypeMenu,
|
||||||
|
|
||||||
|
// "thumb" is not a background.
|
||||||
|
"maingame:2": TypeStatic,
|
||||||
|
|
||||||
// ???
|
// ???
|
||||||
"configure_ultequip:7.5": TypeListBoxUp,
|
"configure_ultequip:7.5": TypeListBoxUp,
|
||||||
"configure_ultequip:7.6": TypeListBoxDown,
|
"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 {
|
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
|
children := record.Children
|
||||||
|
|
||||||
handler, ok := widgetBuilders[record.Type]
|
handler, ok := widgetBuilders[record.Type]
|
||||||
|
@@ -45,6 +45,7 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
|||||||
var downBtn *menus.Record
|
var downBtn *menus.Record
|
||||||
var thumb *menus.Record
|
var thumb *menus.Record
|
||||||
var items []*menus.Record
|
var items []*menus.Record
|
||||||
|
var otherChildren []*menus.Record
|
||||||
|
|
||||||
for _, rec := range menu.Children {
|
for _, rec := range menu.Children {
|
||||||
switch rec.Type {
|
switch rec.Type {
|
||||||
@@ -66,7 +67,8 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
|||||||
}
|
}
|
||||||
thumb = rec
|
thumb = rec
|
||||||
default:
|
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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -95,7 +106,12 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -145,7 +161,7 @@ func registerListBox(d *Driver, menu *menus.Record) ([]*menus.Record, error) {
|
|||||||
|
|
||||||
element.refresh()
|
element.refresh()
|
||||||
|
|
||||||
return nil, nil
|
return otherChildren, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listBox) SetStrings(to []string) {
|
func (l *listBox) SetStrings(to []string) {
|
||||||
|
@@ -16,7 +16,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerBuilder(menus.TypeStatic, noChildren(registerStatic))
|
registerBuilder(menus.TypeStatic, registerStatic) // MainGame has a hypertext child
|
||||||
registerBuilder(menus.TypeHypertext, noChildren(registerHypertext))
|
registerBuilder(menus.TypeHypertext, noChildren(registerHypertext))
|
||||||
registerBuilder(menus.TypeOverlay, noChildren(registerOverlay))
|
registerBuilder(menus.TypeOverlay, noChildren(registerOverlay))
|
||||||
registerBuilder(menus.TypeAnimationSample, noChildren(registerAnimation))
|
registerBuilder(menus.TypeAnimationSample, noChildren(registerAnimation))
|
||||||
@@ -58,9 +58,9 @@ type animationHover struct {
|
|||||||
closing bool
|
closing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerStatic(d *Driver, r *menus.Record) error {
|
func registerStatic(d *Driver, r *menus.Record) ([]*menus.Record, error) {
|
||||||
_, err := registerNoninteractive(d, r)
|
_, err := registerNoninteractive(d, r)
|
||||||
return err
|
return r.Children, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerNoninteractive(d *Driver, r *menus.Record) (*noninteractive, error) {
|
func registerNoninteractive(d *Driver, r *menus.Record) (*noninteractive, error) {
|
||||||
|
Reference in New Issue
Block a user