Compare commits
3 Commits
8ce24ce5f8
...
fd73f03aa5
Author | SHA1 | Date | |
---|---|---|---|
fd73f03aa5 | |||
df1f116b3d | |||
aa43011e8d |
@@ -35,6 +35,7 @@ type AssetStore struct {
|
|||||||
|
|
||||||
// These members are used to store things we've already loaded
|
// These members are used to store things we've already loaded
|
||||||
fonts map[string]*Font
|
fonts map[string]*Font
|
||||||
|
generic *data.Generic
|
||||||
maps map[string]*Map
|
maps map[string]*Map
|
||||||
menus map[string]*Menu
|
menus map[string]*Menu
|
||||||
objs map[string]*Object
|
objs map[string]*Object
|
||||||
|
62
internal/assetstore/data.go
Normal file
62
internal/assetstore/data.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package assetstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.ur.gs/lupine/ordoor/internal/config"
|
||||||
|
"code.ur.gs/lupine/ordoor/internal/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generic returns a struct containing a grab-bag of otherwise-unrelated data
|
||||||
|
// TODO: it would be nice if this could be cleaner
|
||||||
|
func (a *AssetStore) Generic() (*data.Generic, error) {
|
||||||
|
if a.generic != nil {
|
||||||
|
return a.generic, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filename, err := a.lookup("GenericData", "dat", "Data")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
generic, err := data.LoadGeneric(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.generic = generic
|
||||||
|
|
||||||
|
return generic, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AssetStore) DefaultOptions() (*config.Options, error) {
|
||||||
|
cfg := &config.Options{}
|
||||||
|
g, err := a.Generic()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.PlayMovies = intToBool(g.Options[data.OptionMovies])
|
||||||
|
cfg.PlayMusic = intToBool(g.Options[data.OptionMusic])
|
||||||
|
cfg.CombatVoices = intToBool(g.Options[data.OptionCombatVoices])
|
||||||
|
cfg.ShowGrid = intToBool(g.Options[data.OptionGrid])
|
||||||
|
cfg.ShowPaths = intToBool(g.Options[data.OptionShowPaths])
|
||||||
|
cfg.PointSaving = intToBool(g.Options[data.OptionPointSave])
|
||||||
|
cfg.AutoCutLevel = intToBool(g.Options[data.OptionAutoCutLevel])
|
||||||
|
cfg.Animations = intToBool(g.Options[data.OptionShowUnitAnimations])
|
||||||
|
|
||||||
|
// These are overrides of data.OptionCombatResolution. *This* default from
|
||||||
|
// 1998 is no good at all!
|
||||||
|
cfg.XRes = 1280
|
||||||
|
cfg.YRes = 1024
|
||||||
|
|
||||||
|
cfg.MusicVolume = g.Options[data.OptionMusicVolume]
|
||||||
|
cfg.SFXVolume = g.Options[data.OptionSoundEffectsVolume]
|
||||||
|
|
||||||
|
cfg.UnitSpeed = g.Options[data.OptionUnitAnimationSpeed]
|
||||||
|
cfg.AnimSpeed = g.Options[data.OptionEffectAnimationSpeed]
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func intToBool(i int) bool {
|
||||||
|
return i > 0
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@@ -37,8 +38,9 @@ type Options struct {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
filename string `toml:"-"`
|
filename string `toml:"-"`
|
||||||
|
|
||||||
Ordoor `toml:"ordoor"`
|
Defaults *Options `toml:"-"`
|
||||||
Options `toml:"options"`
|
Ordoor `toml:"ordoor"`
|
||||||
|
Options `toml:"options"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load(filename string) (*Config, error) {
|
func Load(filename string) (*Config, error) {
|
||||||
@@ -54,6 +56,12 @@ func Load(filename string) (*Config, error) {
|
|||||||
return &out, err
|
return &out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) HasUnsetOptions() bool {
|
||||||
|
var empty Options
|
||||||
|
|
||||||
|
return c.Options == empty
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) Save() error {
|
func (c *Config) Save() error {
|
||||||
f, err := os.OpenFile(c.filename, os.O_WRONLY, 0644)
|
f, err := os.OpenFile(c.filename, os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,6 +77,16 @@ func (c *Config) DataFile(path string) string {
|
|||||||
return filepath.Join(c.DataDir, path)
|
return filepath.Join(c.DataDir, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) ResetDefaults() error {
|
||||||
|
if c.Defaults == nil {
|
||||||
|
return errors.New("Defaults not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Options = *c.Defaults
|
||||||
|
|
||||||
|
return c.Save()
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Options) ResolutionIndex() int {
|
func (o *Options) ResolutionIndex() int {
|
||||||
if o.XRes == 640 && o.YRes == 480 {
|
if o.XRes == 640 && o.YRes == 480 {
|
||||||
return 1
|
return 1
|
||||||
|
@@ -11,8 +11,8 @@ func (f *Flow) linkOptions() {
|
|||||||
f.configureSlider(options, "2.10", v10Slider) // Music volume slider
|
f.configureSlider(options, "2.10", v10Slider) // Music volume slider
|
||||||
f.configureSlider(options, "2.11", v10Slider) // SFX volume slider
|
f.configureSlider(options, "2.11", v10Slider) // SFX volume slider
|
||||||
|
|
||||||
f.onClick(options, "2.12", f.acceptOptions()) // OK button
|
f.onClick(options, "2.12", f.acceptOptions) // OK button
|
||||||
f.onClick(options, "2.24", f.cancelOptions()) // Cancel button
|
f.onClick(options, "2.24", f.cancelOptions) // Cancel button
|
||||||
|
|
||||||
f.configureSlider(options, "2.26", h9Slider) // Unit speed slider
|
f.configureSlider(options, "2.26", h9Slider) // Unit speed slider
|
||||||
f.configureSlider(options, "2.27", h9Slider) // Animation speed slider
|
f.configureSlider(options, "2.27", h9Slider) // Animation speed slider
|
||||||
@@ -21,31 +21,27 @@ func (f *Flow) linkOptions() {
|
|||||||
// TODO: implement keybindings save/load behaviour
|
// TODO: implement keybindings save/load behaviour
|
||||||
f.onClick(kbd, "3.1", f.setDriver(options)) // Done button
|
f.onClick(kbd, "3.1", f.setDriver(options)) // Done button
|
||||||
f.onClick(kbd, "3.2", f.setDriver(options)) // Cancel button
|
f.onClick(kbd, "3.2", f.setDriver(options)) // Cancel button
|
||||||
f.onClick(kbd, "3.4", func() {}) // Reset to defaults button
|
f.onClick(kbd, "3.4", func() {}) // TODO: Reset to defaults button
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: exiting is a bit OTT. Perhaps display "save failed"?
|
// FIXME: exiting is a bit OTT. Perhaps display "save failed"?
|
||||||
func (f *Flow) acceptOptions() func() {
|
func (f *Flow) acceptOptions() {
|
||||||
return func() {
|
if err := f.optionsIntoConfig(); err != nil {
|
||||||
if err := f.optionsIntoConfig(); err != nil {
|
log.Printf("Saving options to config failed: %v", err)
|
||||||
log.Printf("Saving options to config failed: %v", err)
|
f.exit = err
|
||||||
f.exit = err
|
} else {
|
||||||
} else {
|
f.setDriverNow(main)
|
||||||
f.setDriverNow(main)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: again, exiting is OTT. We're just resetting the state of
|
// FIXME: again, exiting is OTT. We're just resetting the state of
|
||||||
// the interface to the values in config.
|
// the interface to the values in config.
|
||||||
func (f *Flow) cancelOptions() func() {
|
func (f *Flow) cancelOptions() {
|
||||||
return func() {
|
if err := f.configIntoOptions(); err != nil {
|
||||||
if err := f.configIntoOptions(); err != nil {
|
log.Printf("Saving options to config failed: %v", err)
|
||||||
log.Printf("Saving options to config failed: %v", err)
|
f.exit = err
|
||||||
f.exit = err
|
} else {
|
||||||
} else {
|
f.exit = f.returnToLastDriverNow(options)
|
||||||
f.exit = f.returnToLastDriverNow(options)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,8 @@ type Ordoor struct {
|
|||||||
music *audio.Player
|
music *audio.Player
|
||||||
win *ui.Window
|
win *ui.Window
|
||||||
|
|
||||||
|
ship *Ship
|
||||||
|
|
||||||
state gameState
|
state gameState
|
||||||
nextState gameState
|
nextState gameState
|
||||||
|
|
||||||
@@ -53,6 +55,18 @@ func Run(configFile string, overrideX, overrideY int) error {
|
|||||||
return fmt.Errorf("Failed to initialize asset store: %v", err)
|
return fmt.Errorf("Failed to initialize asset store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaults, err := assets.DefaultOptions()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to read option defaults: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Defaults = defaults
|
||||||
|
if cfg.HasUnsetOptions() {
|
||||||
|
if err := cfg.ResetDefaults(); err != nil {
|
||||||
|
return fmt.Errorf("Failed to set options on first-start: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := audio.NewContext(48000); err != nil {
|
if _, err := audio.NewContext(48000); err != nil {
|
||||||
return fmt.Errorf("Failed to set up audio context: %v", err)
|
return fmt.Errorf("Failed to set up audio context: %v", err)
|
||||||
}
|
}
|
||||||
|
70
internal/ordoor/ship.go
Normal file
70
internal/ordoor/ship.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package ordoor
|
||||||
|
|
||||||
|
// Ship encapsulates campaign state, including current location in the campaign,
|
||||||
|
// marines and their stats, supplies, etc.
|
||||||
|
type Ship struct {
|
||||||
|
CurrentMission string
|
||||||
|
|
||||||
|
Squads []*Squad
|
||||||
|
Captain *Character
|
||||||
|
Chaplain *Character
|
||||||
|
Apothecary *Character
|
||||||
|
Techmarines [2]*Character
|
||||||
|
Librarians [4]*Character
|
||||||
|
}
|
||||||
|
|
||||||
|
type SquadType int
|
||||||
|
type CharacterType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SquadTypeTactical SquadType = 0
|
||||||
|
SquadTypeTerminator SquadType = 1
|
||||||
|
SquadTypeAssault SquadType = 2
|
||||||
|
SquadTypeDevastator SquadType = 3
|
||||||
|
|
||||||
|
CharTypeMarine CharacterType = 0
|
||||||
|
CharTypeCaptain CharacterType = 1
|
||||||
|
CharTypeChaplain CharacterType = 2
|
||||||
|
CharTypeApothecary CharacterType = 3
|
||||||
|
CharTypeTechmarine CharacterType = 4
|
||||||
|
CharTypeLibrarian CharacterType = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
type Squad struct {
|
||||||
|
Type SquadType
|
||||||
|
|
||||||
|
Characters []*Character
|
||||||
|
}
|
||||||
|
|
||||||
|
type Character struct {
|
||||||
|
Name string
|
||||||
|
Type CharacterType
|
||||||
|
|
||||||
|
Stats
|
||||||
|
Honours
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stats struct {
|
||||||
|
ActionPoints int
|
||||||
|
Health int
|
||||||
|
Armour int
|
||||||
|
BallisticSkill int
|
||||||
|
WeaponSkill int
|
||||||
|
Strength int
|
||||||
|
Toughness int
|
||||||
|
Initiative int
|
||||||
|
Attacks int
|
||||||
|
Leadership int
|
||||||
|
|
||||||
|
MissionCount int
|
||||||
|
KillCount int
|
||||||
|
|
||||||
|
Experience int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Honours struct {
|
||||||
|
Marksman bool
|
||||||
|
CruxTerminatus bool
|
||||||
|
PuritySeal bool
|
||||||
|
ImperialLaurel bool
|
||||||
|
}
|
Reference in New Issue
Block a user