mirror of
https://github.com/BigJk/end_of_eden.git
synced 2026-02-06 10:48:09 +00:00
feat: transition model, private tags
This commit is contained in:
parent
131824d7fe
commit
68d9de1e7c
9
assets/gen/loading_lines.txt
Normal file
9
assets/gen/loading_lines.txt
Normal file
@ -0,0 +1,9 @@
|
||||
remember to use your consumables
|
||||
watch out for the intent of your enemies
|
||||
collect gold to spend at the merchant
|
||||
may your death be a glorious one
|
||||
rise and shine
|
||||
smell the ashes
|
||||
welcome back from sleep
|
||||
the right crowbar in the wrong place...
|
||||
body slots like HND or ARM can only hold 1 artifact
|
||||
@ -1,10 +1,10 @@
|
||||
register_event("RUST_MITE", {
|
||||
name = "Tasty metals...",
|
||||
description = [[
|
||||
You are walking through the facility hoping to find a way out. After a few turns you hear a strange noise. You look around and come across a strange being.
|
||||
It seems to be eating the metal from the walls. It looks at you and after a few seconds it rushes towards you.
|
||||
|
||||
**It seems to be hostile!**
|
||||
You are walking through the facility hoping to find a way out. After a few turns you hear a strange noise. You look around and come across a strange being.
|
||||
It seems to be eating the metal from the walls. It looks at you and after a few seconds it rushes towards you.
|
||||
|
||||
**It seems to be hostile!**
|
||||
]],
|
||||
tags = {"ACT_0"},
|
||||
choices = {
|
||||
@ -21,11 +21,11 @@ register_event("RUST_MITE", {
|
||||
register_event("CLEAN_BOT", {
|
||||
name = "Corpse. Clean. Engage.",
|
||||
description = [[
|
||||
While exploring the facility you hear a strange noise. Suddenly a strange robot appears from one of the corridors.
|
||||
It seems to be cleaning up the area, but it's not working properly anymore and you can see small sparks coming out of it.
|
||||
It looks at you and says "Corpse. Clean. Engage.".
|
||||
|
||||
**You're not sure what it means, but it doesn't seem to be friendly!**
|
||||
While exploring the facility you hear a strange noise. Suddenly a strange robot appears from one of the corridors.
|
||||
It seems to be cleaning up the area, but it's not working properly anymore and you can see small sparks coming out of it.
|
||||
It looks at you and says "Corpse. Clean. Engage.".
|
||||
|
||||
**You're not sure what it means, but it doesn't seem to be friendly!**
|
||||
]],
|
||||
tags = {"ACT_0"},
|
||||
choices = {
|
||||
|
||||
@ -3,6 +3,8 @@ package game
|
||||
import (
|
||||
"encoding/gob"
|
||||
"github.com/BigJk/end_of_eden/internal/lua/luhelp"
|
||||
"github.com/samber/lo"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -21,6 +23,12 @@ type Artifact struct {
|
||||
BaseGame bool
|
||||
}
|
||||
|
||||
func (a Artifact) PublicTags() []string {
|
||||
return lo.Filter(a.Tags, func(s string, i int) bool {
|
||||
return !strings.HasPrefix(s, "_")
|
||||
})
|
||||
}
|
||||
|
||||
type ArtifactInstance struct {
|
||||
TypeID string
|
||||
GUID string
|
||||
|
||||
@ -3,6 +3,8 @@ package game
|
||||
import (
|
||||
"encoding/gob"
|
||||
"github.com/BigJk/end_of_eden/internal/lua/luhelp"
|
||||
"github.com/samber/lo"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -28,6 +30,12 @@ type Card struct {
|
||||
BaseGame bool
|
||||
}
|
||||
|
||||
func (c Card) PublicTags() []string {
|
||||
return lo.Filter(c.Tags, func(s string, i int) bool {
|
||||
return !strings.HasPrefix(s, "_")
|
||||
})
|
||||
}
|
||||
|
||||
// CardInstance represents an instance of a card owned by some actor.
|
||||
type CardInstance struct {
|
||||
TypeID string
|
||||
|
||||
@ -28,7 +28,7 @@ func ArtifactCard(session *game.Session, guid string, baseHeight int, width int)
|
||||
Background(lipgloss.Color("#343a40")).
|
||||
Foreground(style.BaseWhite)
|
||||
|
||||
tagsText := strings.Join(art.Tags, ", ")
|
||||
tagsText := strings.Join(art.PublicTags(), ", ")
|
||||
|
||||
return artifactStyle.
|
||||
Height(baseHeight).
|
||||
|
||||
@ -24,7 +24,7 @@ func HalfCard(session *game.Session, guid string, active bool, baseHeight int, m
|
||||
cardState := session.GetCardState(guid)
|
||||
|
||||
pointText := strings.Repeat("•", card.PointCost)
|
||||
tagsText := strings.Join(card.Tags, ", ")
|
||||
tagsText := strings.Join(card.PublicTags(), ", ")
|
||||
|
||||
cardCol, _ := colorful.Hex(card.Color)
|
||||
bgCol, _ := colorful.MakeColor(style.BaseGrayDarker)
|
||||
|
||||
@ -55,10 +55,12 @@ func New(parent tea.Model, zones *zone.Manager, session *game.Session) Model {
|
||||
session.Log(game.LogTypeSuccess, "Game started! Good luck...")
|
||||
|
||||
return Model{
|
||||
zones: zones,
|
||||
parent: parent,
|
||||
event: eventview.New(zones, session),
|
||||
merchant: merchant.New(zones, session),
|
||||
zones: zones,
|
||||
parent: parent,
|
||||
event: eventview.New(zones, session),
|
||||
merchant: merchant.New(zones, session),
|
||||
lastGameState: session.GetGameState(),
|
||||
lastEvent: session.GetEventID(),
|
||||
|
||||
Session: session,
|
||||
Start: session.MarkState(),
|
||||
@ -242,7 +244,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
switch m.Session.GetGameState() {
|
||||
currentState := m.Session.GetGameState()
|
||||
currentEvent := m.Session.GetEventID()
|
||||
|
||||
switch currentState {
|
||||
case game.GameStateFight:
|
||||
case game.GameStateMerchant:
|
||||
m.merchant, cmd = m.merchant.Update(msg)
|
||||
@ -254,12 +259,16 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return gameover.New(m.zones, m.Session, m.Start), nil
|
||||
}
|
||||
|
||||
if m.Session.GetGameState() != m.lastGameState || m.Session.GetEventID() != m.lastEvent {
|
||||
//
|
||||
// Show "New Artifacts" / "New Cards" if there are any.
|
||||
//
|
||||
|
||||
if currentState != m.lastGameState || currentEvent != m.lastEvent {
|
||||
diff := m.BeforeStateSwitch.Diff(m.Session)
|
||||
|
||||
m.BeforeStateSwitch = m.Session.MarkState()
|
||||
m.lastGameState = m.Session.GetGameState()
|
||||
m.lastEvent = m.Session.GetEventID()
|
||||
m.lastGameState = currentState
|
||||
m.lastEvent = currentEvent
|
||||
|
||||
if len(diff) > 0 {
|
||||
artifacts := lo.Map(lo.Filter(diff, func(item game.StateCheckpoint, index int) bool {
|
||||
|
||||
@ -112,7 +112,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
log.Println("Error loading save:", err)
|
||||
} else {
|
||||
m.choices = m.choices.Clear()
|
||||
return gameview.New(m, m.zones, session), cmd
|
||||
return m, tea.Sequence(
|
||||
cmd,
|
||||
root.Push(gameview.New(m, m.zones, session)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,11 +134,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
})...)
|
||||
|
||||
m.choices = m.choices.Clear()
|
||||
return m, root.Push(gameview.New(m, m.zones, game.NewSession(
|
||||
game.WithLogging(log.New(f, "SESSION ", log.Ldate|log.Ltime|log.Lshortfile)),
|
||||
game.WithMods(m.settings.GetStrings("mods")),
|
||||
lo.Ternary(os.Getenv("EOE_DEBUG") == "1", game.WithDebugEnabled(8272), nil),
|
||||
)))
|
||||
return m, tea.Sequence(
|
||||
cmd,
|
||||
root.Push(gameview.New(m, m.zones, game.NewSession(
|
||||
game.WithLogging(log.New(f, "SESSION ", log.Ldate|log.Ltime|log.Lshortfile)),
|
||||
game.WithMods(m.settings.GetStrings("mods")),
|
||||
lo.Ternary(os.Getenv("EOE_DEBUG") == "1", game.WithDebugEnabled(8272), nil),
|
||||
))),
|
||||
)
|
||||
case ChoiceAbout:
|
||||
audio.Play("btn_menu")
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"github.com/BigJk/end_of_eden/system/audio"
|
||||
"github.com/BigJk/end_of_eden/ui"
|
||||
"github.com/BigJk/end_of_eden/ui/components"
|
||||
"github.com/BigJk/end_of_eden/ui/root"
|
||||
"github.com/BigJk/end_of_eden/ui/style"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
@ -143,14 +144,14 @@ func (m MenuModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
// Update card table
|
||||
m.cardTable.SetRows(lo.Map(cards, func(guid string, index int) table.Row {
|
||||
card, instance := m.Session.GetCard(guid)
|
||||
return table.Row{m.zones.Mark(ZoneCards+fmt.Sprint(index), card.Name), strings.Join(card.Tags, ", "), fmt.Sprint(instance.Level)}
|
||||
return table.Row{m.zones.Mark(ZoneCards+fmt.Sprint(index), card.Name), strings.Join(card.PublicTags(), ", "), fmt.Sprint(instance.Level)}
|
||||
}))
|
||||
m.cardTable.SetHeight(m.Size.Height - style.HeaderStyle.GetVerticalFrameSize() - 1 - 2)
|
||||
|
||||
// Update artifact table
|
||||
m.artifactTable.SetRows(lo.Map(artifacts, func(guid string, index int) table.Row {
|
||||
art, _ := m.Session.GetArtifact(guid)
|
||||
return table.Row{m.zones.Mark(ZoneArtifacts+fmt.Sprint(index), art.Name), strings.Join(art.Tags, ", "), fmt.Sprintf("%d$", art.Price)}
|
||||
return table.Row{m.zones.Mark(ZoneArtifacts+fmt.Sprint(index), art.Name), strings.Join(art.PublicTags(), ", "), fmt.Sprintf("%d$", art.Price)}
|
||||
}))
|
||||
m.artifactTable.SetHeight(m.Size.Height - style.HeaderStyle.GetVerticalFrameSize() - 1 - 2)
|
||||
|
||||
@ -190,7 +191,7 @@ func (m MenuModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case tea.KeyEnter:
|
||||
if m.list.SelectedItem().(choiceItem).key == ChoiceQuit {
|
||||
m.Session.Close()
|
||||
return nil, nil
|
||||
return nil, root.RemovePushTransitionFunc()
|
||||
}
|
||||
case tea.KeyDown:
|
||||
fallthrough
|
||||
|
||||
73
ui/menus/transition/transition.go
Normal file
73
ui/menus/transition/transition.go
Normal file
@ -0,0 +1,73 @@
|
||||
package transition
|
||||
|
||||
import (
|
||||
"github.com/BigJk/end_of_eden/system/gen"
|
||||
"github.com/BigJk/end_of_eden/ui"
|
||||
"github.com/BigJk/end_of_eden/ui/root"
|
||||
"github.com/BigJk/end_of_eden/ui/style"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
charFull = "●"
|
||||
charHalfLeft = "◐"
|
||||
charHalfRight = "◑"
|
||||
charEmpty = "○"
|
||||
)
|
||||
|
||||
type TickMsg string
|
||||
|
||||
type Model struct {
|
||||
ui.MenuBase
|
||||
|
||||
parent tea.Model
|
||||
created time.Time
|
||||
line string
|
||||
}
|
||||
|
||||
func New(parent tea.Model) Model {
|
||||
return Model{parent: parent, line: gen.GetRandom("loading_lines")}
|
||||
}
|
||||
|
||||
func (m Model) Start() tea.Msg {
|
||||
m.created = time.Now()
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.Size = msg
|
||||
case root.ModelGettingVisibleMsg:
|
||||
m.created = time.Now()
|
||||
case TickMsg:
|
||||
if !m.created.IsZero() && time.Since(m.created) > time.Millisecond*800 {
|
||||
return m.parent, tea.Sequence(root.GettingVisible(), func() tea.Msg {
|
||||
return tea.WindowSizeMsg{Width: m.Size.Width, Height: m.Size.Height}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return m, tea.Tick(time.Second/30, func(t time.Time) tea.Msg {
|
||||
return TickMsg("tick")
|
||||
})
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
elapsed := time.Since(m.created)
|
||||
|
||||
spinner := strings.Split(strings.Repeat(charEmpty, 10), "")
|
||||
pos := elapsed.Milliseconds() / 80 % int64(len(spinner))
|
||||
spinner[pos] = charFull
|
||||
spinner[(pos+1)%int64(len(spinner))] = charHalfLeft
|
||||
spinner[((pos-1)+int64(len(spinner)))%int64(len(spinner))] = charHalfRight
|
||||
|
||||
return lipgloss.Place(m.Size.Width, m.Size.Height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, m.line+"\n", style.RedText.Render(strings.Join(spinner, ""))))
|
||||
}
|
||||
@ -29,37 +29,18 @@ func GettingVisible() tea.Cmd {
|
||||
}
|
||||
}
|
||||
|
||||
// Tooltip represents a tooltip aka overlay message that should be displayed.
|
||||
type Tooltip struct {
|
||||
ID string
|
||||
Content string
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
type PushTransitionFuncMsg func(parent tea.Model) tea.Model
|
||||
|
||||
type TooltipMsg Tooltip
|
||||
|
||||
// TooltipCreate creates a new tooltip.
|
||||
func TooltipCreate(tip Tooltip) tea.Cmd {
|
||||
// PushTransitionFunc pushes a new transition model on the root ui that will be shown between models on the stack.
|
||||
func PushTransitionFunc(fn func(parent tea.Model) tea.Model) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipMsg(tip)
|
||||
return PushTransitionFuncMsg(fn)
|
||||
}
|
||||
}
|
||||
|
||||
type TooltipDeleteMsg string
|
||||
|
||||
// TooltipDelete deletes a tooltip.
|
||||
func TooltipDelete(id string) tea.Cmd {
|
||||
// RemovePushTransitionFunc removes the transition model from the root ui.
|
||||
func RemovePushTransitionFunc() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipDeleteMsg(id)
|
||||
}
|
||||
}
|
||||
|
||||
type TooltipClearMsg struct{}
|
||||
|
||||
// TooltipClear clears all tooltips.
|
||||
func TooltipClear() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipClearMsg(struct{}{})
|
||||
return PushTransitionFuncMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,10 +14,11 @@ import (
|
||||
// the zone manager. The top model of the internal stack is the current model
|
||||
// and will be rendered.
|
||||
type Model struct {
|
||||
zones *zone.Manager
|
||||
stack []tea.Model
|
||||
size tea.WindowSizeMsg
|
||||
tooltips map[string]Tooltip
|
||||
zones *zone.Manager
|
||||
stack []tea.Model
|
||||
size tea.WindowSizeMsg
|
||||
tooltips map[string]Tooltip
|
||||
transitionModel func(parent tea.Model) tea.Model
|
||||
}
|
||||
|
||||
// New creates a new root model.
|
||||
@ -31,7 +32,11 @@ func New(zones *zone.Manager, root tea.Model) Model {
|
||||
|
||||
// PushModel pushes a new model on the stack.
|
||||
func (m Model) PushModel(model tea.Model) Model {
|
||||
m.stack = append(m.stack, model)
|
||||
if m.transitionModel != nil {
|
||||
m.stack = append(m.stack, m.transitionModel(model))
|
||||
} else {
|
||||
m.stack = append(m.stack, model)
|
||||
}
|
||||
m.tooltips = map[string]Tooltip{}
|
||||
return m
|
||||
}
|
||||
@ -71,6 +76,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m = m.PushModel(model)
|
||||
}
|
||||
cmds = append(cmds, GettingVisible())
|
||||
case PushTransitionFuncMsg:
|
||||
m.transitionModel = msg
|
||||
}
|
||||
|
||||
curIndex := len(m.stack) - 1
|
||||
@ -82,22 +89,26 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
if menu, ok := m.stack[curIndex].(ui.Menu); ok && !menu.HasSize() {
|
||||
return m, tea.Batch(cmd, func() tea.Msg {
|
||||
return m.size
|
||||
})
|
||||
}
|
||||
|
||||
if m.stack[curIndex] == nil {
|
||||
// If we remove the top model, we need to send a window size message to the new top model
|
||||
// to avoid the layout to be broken.
|
||||
cmds = append(cmds,
|
||||
func() tea.Msg {
|
||||
return tea.WindowSizeMsg{
|
||||
Width: m.size.Width,
|
||||
Height: m.size.Height,
|
||||
}
|
||||
},
|
||||
GettingVisible(),
|
||||
)
|
||||
m.stack = m.stack[:len(m.stack)-1]
|
||||
} else if menu, ok := m.stack[curIndex].(ui.Menu); ok && !menu.HasSize() {
|
||||
cmds = append(cmds, func() tea.Msg {
|
||||
return tea.WindowSizeMsg{
|
||||
Width: m.size.Width,
|
||||
Height: m.size.Height,
|
||||
}
|
||||
}, GettingVisible())
|
||||
m.stack = m.stack[:len(m.stack)-1]
|
||||
})
|
||||
}
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
|
||||
38
ui/root/tooltip.go
Normal file
38
ui/root/tooltip.go
Normal file
@ -0,0 +1,38 @@
|
||||
package root
|
||||
|
||||
import tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
// Tooltip represents a tooltip aka overlay message that should be displayed.
|
||||
type Tooltip struct {
|
||||
ID string
|
||||
Content string
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
type TooltipMsg Tooltip
|
||||
|
||||
// TooltipCreate creates a new tooltip.
|
||||
func TooltipCreate(tip Tooltip) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipMsg(tip)
|
||||
}
|
||||
}
|
||||
|
||||
type TooltipDeleteMsg string
|
||||
|
||||
// TooltipDelete deletes a tooltip.
|
||||
func TooltipDelete(id string) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipDeleteMsg(id)
|
||||
}
|
||||
}
|
||||
|
||||
type TooltipClearMsg struct{}
|
||||
|
||||
// TooltipClear clears all tooltips.
|
||||
func TooltipClear() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return TooltipClearMsg(struct{}{})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user