diff options
| -rw-r--r-- | go/TODO | 1 | ||||
| -rw-r--r-- | go/client/game.go | 15 | ||||
| -rw-r--r-- | go/game/action.go | 82 | ||||
| -rw-r--r-- | go/game/card.go | 9 | ||||
| -rw-r--r-- | go/game/permanent.go | 9 | ||||
| -rw-r--r-- | go/game/state.go | 11 | ||||
| -rw-r--r-- | go/game/unit.go | 13 | ||||
| -rw-r--r-- | go/ui/choice.go | 62 | ||||
| -rw-r--r-- | go/ui/collection.go | 5 |
9 files changed, 128 insertions, 79 deletions
@@ -1,7 +1,6 @@ * implement pile dropping * implement artifcat action * move - * switch * implement equipment actions * equip * drop diff --git a/go/client/game.go b/go/client/game.go index 8447e452..32fb5f2f 100644 --- a/go/client/game.go +++ b/go/client/game.go @@ -409,18 +409,12 @@ func (g *Game) highlightTargets() { func (g *Game) Update() error { g.handlePlayerNotifications() - - if err := g.Collection.Update(); err != nil { - return nil - } - - x, y := ebiten.CursorPosition() - - obj := g.findObjectAt(x, y) - g.highlightTargets() if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { + x, y := ebiten.CursorPosition() + obj := g.findObjectAt(x, y) + if g.prompt != nil { if err := g.prompt.Add(obj); err == nil { g.AddHighlight(obj) @@ -445,7 +439,8 @@ func (g *Game) Update() error { g.prompt.ClearSelections() } } - return nil + + return g.Collection.Update() } func (g *Game) Draw(screen *ebiten.Image) { diff --git a/go/game/action.go b/go/game/action.go index 77e9743f..1e25cd67 100644 --- a/go/game/action.go +++ b/go/game/action.go @@ -161,13 +161,7 @@ func NewMoveAction(u *Unit) *MoveAction { u.move(s, tile) } - a.costFunc = func(*State) bool { - if u.AvailMoveActions < 1 { - return false - } - u.AvailMoveActions-- - return true - } + a.costFunc = genMoveActionCost(u) return a } @@ -182,6 +176,36 @@ func (a *MoveAction) String() string { return fmt.Sprintf("%s -> %v", u.FmtWController(), t.Position) } +func genBaseActionCost(u *Unit, attack, move int) ActionCostFunc { + return func(*State) bool { + if u.AvailAttackActions < attack || u.AvailMoveActions < move { + return false + } + u.AvailAttackActions -= attack + u.AvailMoveActions -= move + return true + } +} + +func genAttackActionCost(u *Unit) ActionCostFunc { + return genBaseActionCost(u, 1, 0) +} + +func genMoveActionCost(u *Unit) ActionCostFunc { + return genBaseActionCost(u, 0, 1) +} + +func genFullActionCost(u *Unit) ActionCostFunc { + return func(*State) bool { + if u.AvailAttackActions < 1 || u.AvailMoveActions < 1 { + return false + } + u.AvailAttackActions = 0 + u.AvailMoveActions = 0 + return true + } +} + type AttackAction struct { ActionBase } @@ -200,13 +224,7 @@ func NewAttackAction(u *Unit) *AttackAction { s.Fight(u, a.Target().sel[0].(Permanent)) } - a.costFunc = func(*State) bool { - if u.AvailAttackActions < 1 { - return false - } - u.AvailAttackActions-- - return true - } + a.costFunc = genAttackActionCost(u) return a } @@ -221,6 +239,33 @@ func (a *AttackAction) String() string { return fmt.Sprintf("%s x %v", u.FmtWController(), target.Tile().Position) } +type ArtifactSwitchAction struct { + ActionBase + Artifact Permanent +} + +func newArtifactSwitchAction(u *Unit, artifact Permanent) *ArtifactSwitchAction { + a := &ArtifactSwitchAction{ + ActionBase{ + source: u, + Card: u.Card(), + }, + artifact, + } + + a.resolveFunc = func(s *State) { + s.switchPermanents(a.Source().(*Unit), a.Artifact) + } + + a.costFunc = genMoveActionCost(u) + + return a +} + +func (a *ArtifactSwitchAction) String() string { + return fmt.Sprintf("%s <-> %v", a.Source().(*Unit).FmtWController(), a.Artifact) +} + type FullAction struct { ActionBase desc string @@ -242,14 +287,7 @@ func NewFullAction(u *Unit, proto ActionFuncPrototype, desc string) *FullAction rf(s) } - a.costFunc = func(*State) bool { - if u.AvailAttackActions < 1 && u.AvailMoveActions < 1 { - return false - } - u.AvailAttackActions-- - u.AvailMoveActions-- - return true - } + a.costFunc = genFullActionCost(u) return a } diff --git a/go/game/card.go b/go/game/card.go index f305634b..d9d2c81b 100644 --- a/go/game/card.go +++ b/go/game/card.go @@ -80,6 +80,15 @@ func (ct CardType) IsPermanent() bool { } } +func (ct CardType) IsArtifact() bool { + switch ct { + case CardTypes.Artifact, CardTypes.Equipment, CardTypes.Potion: + return true + default: + return false + } +} + type cardImplementation interface { spawnTiles(*State, *Player) []*Tile fullActions(*Unit) []*FullAction diff --git a/go/game/permanent.go b/go/game/permanent.go index db2dcaff..cd5cbfe6 100644 --- a/go/game/permanent.go +++ b/go/game/permanent.go @@ -203,6 +203,15 @@ func enterTile(p Permanent, t *Tile) { p.Card().Impl.onEntering(t) } +func enterTileOrPile(p Permanent, t *Tile) { + if t.Permanent == nil { + enterTile(p, t) + } else { + AddPermanentToPile(t.Permanent, p) + p.SetTile(nil) + } +} + func leaveTile(p Permanent) { if p.Tile() != nil { p.Card().Impl.onLeaving(p.Tile()) diff --git a/go/game/state.go b/go/game/state.go index 7fa6e1bf..4af56b10 100644 --- a/go/game/state.go +++ b/go/game/state.go @@ -362,6 +362,17 @@ func (s *State) MoveUnit(u *Unit, t *Tile) { u.move(s, t) } +func (s *State) switchPermanents(p1 Permanent, p2 Permanent) { + t1 := TileOrContainingPermTile(p1) + t2 := TileOrContainingPermTile(p2) + + leaveTile(p1) + leaveTile(p2) + + enterTileOrPile(p1, t2) + enterTileOrPile(p2, t1) +} + func (s *State) FilterUnits(filter func(*Unit) bool) []*Unit { units := []*Unit{} for _, u := range s.Units { diff --git a/go/game/unit.go b/go/game/unit.go index 51383b77..bc9cad3f 100644 --- a/go/game/unit.go +++ b/go/game/unit.go @@ -99,12 +99,7 @@ func (u *Unit) move(s *State, tile *Tile) { leaveTile(u) } - if tile.Permanent == nil { - enterTile(u, tile) - } else { // crew permanent at tile - AddPermanentToPile(tile.Permanent, u) - u.tile = nil - } + enterTileOrPile(u, tile) } func (u *Unit) MoveRangeTiles(m *Map) []*Tile { @@ -200,6 +195,12 @@ func (u *Unit) AvailSlowActions() (actions []Action) { for _, p := range u.FullActions { actions = append(actions, p) } + + for _, t := range TilesInRange(m, u, 1) { + if t.Permanent != nil && t.Permanent.Card().Type.IsArtifact() { + actions = append(actions, newArtifactSwitchAction(u, t.Permanent)) + } + } } return actions diff --git a/go/ui/choice.go b/go/ui/choice.go index 28878604..04b8f725 100644 --- a/go/ui/choice.go +++ b/go/ui/choice.go @@ -9,66 +9,50 @@ import ( ) type Choice struct { - X, Y int - Width, choiceHeight int - choices []string - onClick func(*Choice, int, int) - buttons []Button + TextBox + choices []interface{} + onClick func(*Choice, int, int) } func choiceButtonOnClickDummy(b *SimpleButton) {} -func NewChoice(x, y int, width, choiceHeight int, choices []string, - onClick func(*Choice, int, int), -) *Choice { - c := &Choice{x, y, width, choiceHeight, choices, onClick, []Button{}} - - for i, choice := range c.choices { - b := NewSimpleButton(c.X, c.Y+i*c.choiceHeight, c.Width, c.choiceHeight, choice, - choiceButtonOnClickDummy) +func NewChoice(x, y int, choices []interface{}, onClick func(*Choice, int, int)) *Choice { + c := &Choice{ + TextBox: *(NewAutoTextBox(x, y, "")), + choices: choices, + onClick: onClick, + } - c.buttons = append(c.buttons, b) + c.renderImpl = func() *ebiten.Image { + c.setText() + return c.render() } return c } -func (c *Choice) Draw(screen *ebiten.Image) { - for _, b := range c.buttons { - b.Draw(screen) +func (c *Choice) setText() { + c.Width, c.Height = -1, -1 + t := "" + for _, choice := range c.choices { + t = fmt.Sprintf("%s%v\n", t, choice) } + + c.text = t[:len(t)-1] } func (c *Choice) GetChoosen(x, y int) int { - return (y - c.Y) / c.choiceHeight + i := (y - c.Y) / (c.Height / len(c.choices)) + return i } func (c *Choice) Click(x, y int) { c.onClick(c, x, y) } -func (c *Choice) Contains(x, y int) bool { - height := len(c.choices) * c.choiceHeight - return x >= c.X && x <= c.X+c.Width && y >= c.Y && y <= c.Y+height -} - -func (c *Choice) FindObjectAt(x, y int) interface{} { return nil } -func (c *Choice) Render() *ebiten.Image { return nil } - -func NewObjectChoice(x, y int, objs []interface{}, onClick func(*Choice, int, int)) *Choice { - // TODO: use dynamic with width and height - width := 200 - choiceHeight := 40 - labels := make([]string, 0, len(objs)) - for _, obj := range objs { - labels = append(labels, fmt.Sprintf("%v", obj)) - } - return NewChoice(x, y, width, choiceHeight, labels, onClick) -} - func NewActionChoice(x, y int, actions []game.Action, onClick func(*Choice, int, int)) *Choice { - return NewObjectChoice(x, y, utils.TypedSliceToInterfaceSlice(actions), onClick) + return NewChoice(x, y, utils.TypedSliceToInterfaceSlice(actions), onClick) } func NewPermChoice(x, y int, perms []game.Permanent, onClick func(*Choice, int, int)) *Choice { - return NewObjectChoice(x, y, utils.TypedSliceToInterfaceSlice(perms), onClick) + return NewChoice(x, y, utils.TypedSliceToInterfaceSlice(perms), onClick) } diff --git a/go/ui/collection.go b/go/ui/collection.go index d75e3267..027d0d99 100644 --- a/go/ui/collection.go +++ b/go/ui/collection.go @@ -69,7 +69,10 @@ func (c *Collection) Update() error { x, y := ebiten.CursorPosition() var activeWidget Widget - for _, w := range c.widgets { + // Iterate the widget in reverse order to ensure that upper widgets are + // considered first + for i := len(c.widgets) - 1; i >= 0; i-- { + w := c.widgets[i] if !w.Contains(x, y) { continue } |
