package game import ( "fmt" "image/color" "sort" "strings" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/vector" "gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/progress" ) // SkillsScene är skillträdet: grenar med noder, kostnad i skillpoäng och krav. type SkillsScene struct { back Scene skills []progress.Skill sel int top int msg string } const skillRows = 8 // NewSkillsScene listar skills gren för gren. func NewSkillsScene(g *Game, back Scene) *SkillsScene { sk := append([]progress.Skill(nil), g.Catalog.Skills...) sort.SliceStable(sk, func(i, j int) bool { if sk[i].Branch != sk[j].Branch { return sk[i].Branch < sk[j].Branch } return len(sk[i].Requires) < len(sk[j].Requires) }) return &SkillsScene{back: back, skills: sk} } func (s *SkillsScene) Update(g *Game) error { if backJustPressed() || skillsJustPressed() { g.SetScene(s.back) return nil } if n := len(s.skills); n > 0 { s.sel = (s.sel + menuMove() + n) % n if s.sel < s.top { s.top = s.sel } if s.sel >= s.top+skillRows { s.top = s.sel - skillRows + 1 } if confirmJustPressed() { sk := s.skills[s.sel] switch { case g.Progress.Has(sk.ID): s.msg = g.Assets.T("skills.already") case g.Progress.Unlock(g.Catalog, sk.ID): s.msg = fmt.Sprintf(g.Assets.T("skills.unlocked"), sk.Name.Get(UILang)) g.Save() case g.Progress.SkillPoints < sk.Cost: s.msg = fmt.Sprintf(g.Assets.T("skills.need_points"), sk.Cost) default: s.msg = g.Assets.T("skills.need_req") } } } return nil } func (s *SkillsScene) Draw(g *Game, screen *ebiten.Image) { a := g.Assets p := g.Progress screen.Fill(color.RGBA{24, 20, 37, 255}) vector.DrawFilledRect(screen, 0, 0, ScreenW, 22, color.RGBA{38, 43, 68, 255}, false) a.DrawBig(screen, a.T("skills.title"), 8, 5, colText) hdr := fmt.Sprintf("%s %d %s %d %s %d", a.T("map.skill_points"), p.SkillPoints, a.T("map.level"), p.Level(), a.T("skills.to_next"), progress_XPToNext(p.XP)) a.Draw(screen, hdr, ScreenW-8-a.Width(hdr), 6, colKnown) y0 := 30 for i := s.top; i < len(s.skills) && i < s.top+skillRows; i++ { sk := s.skills[i] y := y0 + (i-s.top)*LineH if i == s.sel { vector.DrawFilledRect(screen, 4, float32(y-1), ScreenW-8, LineH, colBar, false) } col, status := colDim, strings.Repeat("●", sk.Cost) switch { case p.Has(sk.ID): col, status = colGood, "✓" case p.CanUnlock(g.Catalog, sk.ID): col = colKnown } a.Draw(screen, sk.Branch, 8, y, colDim) a.Draw(screen, sk.Name.Get(UILang), 80, y, col) if len(sk.Requires) > 0 { req := make([]string, len(sk.Requires)) for k, r := range sk.Requires { req[k] = g.Catalog.Skill(r).Name.Get(UILang) } a.Draw(screen, "← "+strings.Join(req, ", "), 190, y, colDim) } a.Draw(screen, status, ScreenW-8-a.Width(status), y, col) } if len(s.skills) > 0 { sel := s.skills[s.sel] for i, l := range a.wrapLine(plainLine(sel.Desc.Get(UILang), colText), ScreenW-16) { a.drawLines(screen, []line{l}, 8, 130+i*LineH) } } if s.msg != "" { a.Draw(screen, s.msg, 8, ScreenH-26, colKnown) } a.Draw(screen, a.T("skills.hint"), 8, ScreenH-13, colDim) }