mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 15:46:51 -05:00
Inital skilltree panel implementation (#782)
* d2ui/UIFrame: Refactor into its own class it's not useful to have the handling of frames for the inventory/herostate/skilltree/quest panels individually in each of those. * d2ui/button: Fix crash when a buttonlayout was not allowing FrameChange When AllowFrameChange is false we do not create pressedSurface. So if we press the button the game will crash. * d2ui/button: Allow label-only buttons At least for the skillmenu we need buttons were the graphic size does not match the buttonsize. So let's render the graphic in there and make the button label only. * d2hero/hero_state_factory: Give all heroes their class specific skills * d2player/gamecontrols: Fix wrong inventory/stats layouts for exp chars For Druid/Assassin the inventory frame was rendered for a 640x480 resolution. This brings it in line with all other characters. * d2player: Add inital Skilltree panel * d2player/game_controls: Enable skilltree Note here, that the inventory panel and skilltree panel can overlap. * d2player/skilltree: Add skillicon rendering Note here, that I couldn't figure out how to render them dark if no skillpoints are invested. Signed-off-by: juander <juander@rumtueddeln.de>
This commit is contained in:
parent
209cc19c89
commit
e5dae4e5d8
@ -43,3 +43,26 @@ func (h Hero) GetToken() string {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetToken3 returns a 3 letter token
|
||||
func (h Hero) GetToken3() string {
|
||||
switch h {
|
||||
case HeroBarbarian:
|
||||
return "BAR"
|
||||
case HeroNecromancer:
|
||||
return "NEC"
|
||||
case HeroPaladin:
|
||||
return "PAL"
|
||||
case HeroAssassin:
|
||||
return "ASS"
|
||||
case HeroSorceress:
|
||||
return "SOR"
|
||||
case HeroAmazon:
|
||||
return "AMA"
|
||||
case HeroDruid:
|
||||
return "DRU"
|
||||
default:
|
||||
log.Fatalf("Unknown hero token: %d", h)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func (f *HeroStateFactory) CreateHeroState(
|
||||
}
|
||||
|
||||
defaultStats := f.asset.Records.Character.Stats[hero]
|
||||
skillState, err := f.CreateHeroSkillsState(defaultStats)
|
||||
skillState, err := f.CreateHeroSkillsState(defaultStats, hero)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -85,7 +85,7 @@ func (f *HeroStateFactory) GetAllHeroStates() ([]*HeroState, error) {
|
||||
classStats := f.asset.Records.Character.Stats[gameState.HeroType]
|
||||
gameState.Stats = f.CreateHeroStatsState(gameState.HeroType, classStats)
|
||||
|
||||
skillState, err := f.CreateHeroSkillsState(classStats)
|
||||
skillState, err := f.CreateHeroSkillsState(classStats, gameState.HeroType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -104,7 +104,7 @@ func (f *HeroStateFactory) GetAllHeroStates() ([]*HeroState, error) {
|
||||
}
|
||||
|
||||
// CreateHeroSkillsState will assemble the hero skills from the class stats record.
|
||||
func (f *HeroStateFactory) CreateHeroSkillsState(classStats *d2records.CharStatsRecord) (map[int]*HeroSkill, error) {
|
||||
func (f *HeroStateFactory) CreateHeroSkillsState(classStats *d2records.CharStatsRecord, heroType d2enum.Hero) (map[int]*HeroSkill, error) {
|
||||
baseSkills := map[int]*HeroSkill{}
|
||||
|
||||
for idx := range classStats.BaseSkill {
|
||||
@ -122,6 +122,16 @@ func (f *HeroStateFactory) CreateHeroSkillsState(classStats *d2records.CharStats
|
||||
baseSkills[skill.ID] = skill
|
||||
}
|
||||
|
||||
skillList := f.asset.Records.Skill.Details
|
||||
token := strings.ToLower(heroType.GetToken3())
|
||||
for idx := range skillList {
|
||||
if skillList[idx].Charclass == token {
|
||||
skill, _ := f.CreateHeroSkill(0, skillList[idx].Skill)
|
||||
baseSkills[skill.ID] = skill
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
skillRecord, err := f.CreateHeroSkill(1, "Attack")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -18,9 +18,9 @@ func skillDescriptionLoader(r *RecordManager, d *d2txt.DataDictionary) error {
|
||||
for d.Next() {
|
||||
record := &SkillDescriptionRecord{
|
||||
d.String("skilldesc"),
|
||||
d.String("SkillPage"),
|
||||
d.String("SkillRow"),
|
||||
d.String("SkillColumn"),
|
||||
d.Number("SkillPage"),
|
||||
d.Number("SkillRow"),
|
||||
d.Number("SkillColumn"),
|
||||
d.String("ListRow"),
|
||||
d.String("ListPool"),
|
||||
d.Number("IconCel"),
|
||||
|
@ -9,9 +9,9 @@ type SkillDescriptions map[string]*SkillDescriptionRecord
|
||||
// generating text strings for skills.
|
||||
type SkillDescriptionRecord struct {
|
||||
Name string // skilldesc
|
||||
SkillPage string // SkillPage
|
||||
SkillRow string // SkillRow
|
||||
SkillColumn string // SkillColumn
|
||||
SkillPage int // SkillPage
|
||||
SkillRow int // SkillRow
|
||||
SkillColumn int // SkillColumn
|
||||
ListRow string // ListRow
|
||||
ListPool string // ListPool
|
||||
IconCel int // IconCel
|
||||
|
@ -41,6 +41,10 @@ const (
|
||||
ButtonTypeMinipanelQuest ButtonType = 18
|
||||
ButtonTypeMinipanelMen ButtonType = 19
|
||||
ButtonTypeSquareClose ButtonType = 20
|
||||
ButtonTypeSkillTreeTab ButtonType = 21
|
||||
|
||||
ButtonNoFixedWidth int = -1
|
||||
ButtonNoFixedHeight int = -1
|
||||
)
|
||||
|
||||
const (
|
||||
@ -50,6 +54,7 @@ const (
|
||||
const (
|
||||
greyAlpha100 = 0x646464ff
|
||||
lightGreyAlpha75 = 0x808080c3
|
||||
whiteAlpha100 = 0xffffffff
|
||||
)
|
||||
|
||||
// ButtonLayout defines the type of buttons
|
||||
@ -65,6 +70,10 @@ type ButtonLayout struct {
|
||||
TextOffset int
|
||||
Toggleable bool
|
||||
AllowFrameChange bool
|
||||
HasImage bool
|
||||
FixedWidth int
|
||||
FixedHeight int
|
||||
LabelColor uint32
|
||||
}
|
||||
|
||||
const (
|
||||
@ -111,6 +120,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
PaletteName: d2resource.PaletteUnits,
|
||||
FontPath: d2resource.FontExocet10,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeShort: {
|
||||
XSegments: buttonShortSegmentsX,
|
||||
@ -121,6 +134,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
PaletteName: d2resource.PaletteUnits,
|
||||
FontPath: d2resource.FontRediculous,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeMedium: {
|
||||
XSegments: buttonMediumSegmentsX,
|
||||
@ -129,6 +146,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
PaletteName: d2resource.PaletteUnits,
|
||||
FontPath: d2resource.FontExocet10,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeTall: {
|
||||
XSegments: buttonTallSegmentsX,
|
||||
@ -138,6 +159,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
PaletteName: d2resource.PaletteUnits,
|
||||
FontPath: d2resource.FontExocet10,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeOkCancel: {
|
||||
XSegments: buttonOkCancelSegmentsX,
|
||||
@ -147,6 +172,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
PaletteName: d2resource.PaletteUnits,
|
||||
FontPath: d2resource.FontRediculous,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeRun: {
|
||||
XSegments: buttonRunSegmentsX,
|
||||
@ -157,6 +186,10 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
Toggleable: true,
|
||||
FontPath: d2resource.FontRediculous,
|
||||
AllowFrameChange: true,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeSquareClose: {
|
||||
XSegments: buttonBuySellSegmentsX,
|
||||
@ -168,6 +201,25 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
FontPath: d2resource.Font30,
|
||||
AllowFrameChange: true,
|
||||
BaseFrame: closeButtonBaseFrame,
|
||||
HasImage: true,
|
||||
FixedWidth: ButtonNoFixedWidth,
|
||||
FixedHeight: ButtonNoFixedHeight,
|
||||
LabelColor: greyAlpha100,
|
||||
},
|
||||
ButtonTypeSkillTreeTab: {
|
||||
XSegments: 1,
|
||||
YSegments: 1,
|
||||
DisabledFrame: 7,
|
||||
ResourceName: d2resource.SkillsPanelAmazon,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
Toggleable: false,
|
||||
FontPath: d2resource.Font16,
|
||||
AllowFrameChange: false,
|
||||
BaseFrame: 7,
|
||||
HasImage: false,
|
||||
FixedWidth: 93,
|
||||
FixedHeight: 107,
|
||||
LabelColor: whiteAlpha100,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -209,7 +261,7 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
||||
lbl := ui.NewLabel(buttonLayout.FontPath, d2resource.PaletteUnits)
|
||||
|
||||
lbl.SetText(text)
|
||||
lbl.Color[0] = d2util.Color(greyAlpha100)
|
||||
lbl.Color[0] = d2util.Color(buttonLayout.LabelColor)
|
||||
lbl.Alignment = d2gui.HorizontalAlignCenter
|
||||
|
||||
buttonSprite, err := ui.NewSprite(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||
@ -217,25 +269,32 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
if buttonLayout.FixedWidth > 0 {
|
||||
btn.width = buttonLayout.FixedWidth
|
||||
} else {
|
||||
for i := 0; i < buttonLayout.XSegments; i++ {
|
||||
w, _, err := buttonSprite.GetFrameSize(i)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < buttonLayout.XSegments; i++ {
|
||||
w, _, err := buttonSprite.GetFrameSize(i)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
btn.width += w
|
||||
btn.width += w
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < buttonLayout.YSegments; i++ {
|
||||
_, h, err := buttonSprite.GetFrameSize(i * buttonLayout.YSegments)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
if buttonLayout.FixedHeight > 0 {
|
||||
btn.height = buttonLayout.FixedHeight
|
||||
} else {
|
||||
for i := 0; i < buttonLayout.YSegments; i++ {
|
||||
_, h, err := buttonSprite.GetFrameSize(i * buttonLayout.YSegments)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
btn.height += h
|
||||
btn.height += h
|
||||
}
|
||||
}
|
||||
|
||||
btn.normalSurface, err = ui.renderer.NewSurface(btn.width, btn.height, d2enum.FilterNearest)
|
||||
@ -259,10 +318,12 @@ func (v *Button) renderFrames(btnSprite *Sprite, btnLayout *ButtonLayout, label
|
||||
|
||||
totalButtonTypes := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments)
|
||||
|
||||
err = btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame)
|
||||
if v.buttonLayout.HasImage {
|
||||
err = btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("failed to render button normalSurface, err: %v\n", err)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to render button normalSurface, err: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, labelHeight := label.GetSize()
|
||||
@ -272,7 +333,7 @@ func (v *Button) renderFrames(btnSprite *Sprite, btnLayout *ButtonLayout, label
|
||||
label.SetPosition(xOffset, textY)
|
||||
label.Render(v.normalSurface)
|
||||
|
||||
if btnLayout.AllowFrameChange {
|
||||
if btnLayout.HasImage && btnLayout.AllowFrameChange {
|
||||
frameOffset := 0
|
||||
xSeg, ySeg, baseFrame := btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame
|
||||
|
||||
@ -395,7 +456,11 @@ func (v *Button) Render(target d2interface.Surface) error {
|
||||
case v.toggled && v.pressed:
|
||||
err = target.Render(v.pressedToggledSurface)
|
||||
case v.pressed:
|
||||
err = target.Render(v.pressedSurface)
|
||||
if v.buttonLayout.AllowFrameChange {
|
||||
err = target.Render(v.pressedSurface)
|
||||
} else {
|
||||
err = target.Render(v.normalSurface)
|
||||
}
|
||||
case v.toggled:
|
||||
err = target.Render(v.toggledSurface)
|
||||
default:
|
||||
|
235
d2core/d2ui/frame.go
Normal file
235
d2core/d2ui/frame.go
Normal file
@ -0,0 +1,235 @@
|
||||
package d2ui
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
type UIFrame struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *UIManager
|
||||
frame *Sprite
|
||||
originX int
|
||||
originY int
|
||||
frameOrientation FrameOrientation
|
||||
}
|
||||
|
||||
type FrameOrientation = int
|
||||
const(
|
||||
FrameLeft FrameOrientation = iota
|
||||
FrameRight
|
||||
)
|
||||
|
||||
func NewUIFrame (
|
||||
asset *d2asset.AssetManager,
|
||||
uiManager *UIManager,
|
||||
frameOrientation FrameOrientation,
|
||||
) *UIFrame {
|
||||
var originX, originY = 0,0
|
||||
|
||||
switch frameOrientation {
|
||||
case FrameLeft:
|
||||
originX = 0
|
||||
originY = 0
|
||||
case FrameRight:
|
||||
originX = 400
|
||||
originY = 0
|
||||
}
|
||||
frame := &UIFrame {
|
||||
asset : asset,
|
||||
uiManager: uiManager,
|
||||
frameOrientation: frameOrientation,
|
||||
originX: originX,
|
||||
originY: originY,
|
||||
}
|
||||
frame.Load()
|
||||
return frame
|
||||
}
|
||||
|
||||
func (u *UIFrame) Load() {
|
||||
sprite, err := u.uiManager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
u.frame = sprite
|
||||
}
|
||||
|
||||
func (u *UIFrame) Render(target d2interface.Surface) error {
|
||||
switch u.frameOrientation {
|
||||
case FrameLeft:
|
||||
return u.renderLeft(target)
|
||||
case FrameRight:
|
||||
return u.renderRight(target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UIFrame) renderLeft(target d2interface.Surface) error {
|
||||
x, y := u.originX, u.originY
|
||||
|
||||
// Frame
|
||||
// Top left
|
||||
if err := u.frame.SetCurrentFrame(0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h := u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
y += h
|
||||
|
||||
// Top right
|
||||
if err := u.frame.SetCurrentFrame(1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, u.originY+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x = u.originX
|
||||
|
||||
// Right
|
||||
if err := u.frame.SetCurrentFrame(2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = u.frame.GetCurrentFrameSize()
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
y += h
|
||||
|
||||
// Bottom left
|
||||
if err := u.frame.SetCurrentFrame(3); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
|
||||
// Bottom right
|
||||
if err := u.frame.SetCurrentFrame(4); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UIFrame) renderRight(target d2interface.Surface) error {
|
||||
x, y := u.originX, u.originY
|
||||
|
||||
// Frame
|
||||
// Top left
|
||||
if err := u.frame.SetCurrentFrame(5); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h := u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
|
||||
// Top right
|
||||
if err := u.frame.SetCurrentFrame(6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
y += h
|
||||
|
||||
// Right
|
||||
if err := u.frame.SetCurrentFrame(7); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
y += h
|
||||
|
||||
// Bottom right
|
||||
if err := u.frame.SetCurrentFrame(8); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x -= w
|
||||
|
||||
// Bottom left
|
||||
if err := u.frame.SetCurrentFrame(9); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = u.frame.GetCurrentFrameSize()
|
||||
|
||||
u.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := u.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UIFrame) GetFrameBounds() (width, height int) {
|
||||
return u.frame.GetFrameBounds()
|
||||
}
|
||||
|
||||
func (u *UIFrame) GetFrameCount() int {
|
||||
return u.frame.GetFrameCount()
|
||||
}
|
@ -58,6 +58,7 @@ type GameControls struct {
|
||||
escapeMenu *EscapeMenu
|
||||
ui *d2ui.UIManager
|
||||
inventory *Inventory
|
||||
skilltree *SkillTree
|
||||
heroStatsPanel *HeroStatsPanel
|
||||
HelpOverlay *help.Overlay
|
||||
miniPanel *miniPanel
|
||||
@ -151,13 +152,13 @@ func NewGameControls(
|
||||
|
||||
switch hero.Class {
|
||||
case d2enum.HeroAssassin:
|
||||
inventoryRecordKey = "Assassin"
|
||||
inventoryRecordKey = "Assassin2"
|
||||
case d2enum.HeroAmazon:
|
||||
inventoryRecordKey = "Amazon2"
|
||||
case d2enum.HeroBarbarian:
|
||||
inventoryRecordKey = "Barbarian2"
|
||||
case d2enum.HeroDruid:
|
||||
inventoryRecordKey = "Druid"
|
||||
inventoryRecordKey = "Druid2"
|
||||
case d2enum.HeroNecromancer:
|
||||
inventoryRecordKey = "Necromancer2"
|
||||
case d2enum.HeroPaladin:
|
||||
@ -191,6 +192,7 @@ func NewGameControls(
|
||||
inputListener: inputListener,
|
||||
mapRenderer: mapRenderer,
|
||||
inventory: NewInventory(asset, ui, inventoryRecord),
|
||||
skilltree: NewSkillTree(hero.Skills, hero.Class, asset, renderer, ui, guiManager),
|
||||
heroStatsPanel: NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats),
|
||||
HelpOverlay: help.NewHelpOverlay(asset, renderer, ui, guiManager),
|
||||
miniPanel: newMiniPanel(asset, ui, isSinglePlayer),
|
||||
@ -307,6 +309,9 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
|
||||
case d2enum.KeyI:
|
||||
g.inventory.Toggle()
|
||||
g.updateLayout()
|
||||
case d2enum.KeyT:
|
||||
g.skilltree.Toggle()
|
||||
g.updateLayout()
|
||||
case d2enum.KeyC:
|
||||
g.heroStatsPanel.Toggle()
|
||||
g.updateLayout()
|
||||
@ -347,6 +352,12 @@ func (g *GameControls) onEscKey() {
|
||||
escHandled = true
|
||||
}
|
||||
|
||||
if g.skilltree.IsOpen() {
|
||||
g.skilltree.Close()
|
||||
|
||||
escHandled = true
|
||||
}
|
||||
|
||||
if g.heroStatsPanel.IsOpen() {
|
||||
g.heroStatsPanel.Close()
|
||||
|
||||
@ -521,6 +532,7 @@ func (g *GameControls) Load() {
|
||||
g.loadUIButtons()
|
||||
|
||||
g.inventory.Load()
|
||||
g.skilltree.Load()
|
||||
g.heroStatsPanel.Load()
|
||||
g.HelpOverlay.Load()
|
||||
}
|
||||
@ -570,8 +582,7 @@ func (g *GameControls) isLeftPanelOpen() bool {
|
||||
}
|
||||
|
||||
func (g *GameControls) isRightPanelOpen() bool {
|
||||
// TODO: add skills tree panel
|
||||
return g.inventory.IsOpen()
|
||||
return g.inventory.IsOpen() || g.skilltree.IsOpen()
|
||||
}
|
||||
|
||||
func (g *GameControls) isInActiveMenusRect(px, py int) bool {
|
||||
@ -655,6 +666,10 @@ func (g *GameControls) Render(target d2interface.Surface) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.skilltree.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
width, height := target.GetSize()
|
||||
offset := 0
|
||||
|
||||
@ -1137,6 +1152,11 @@ func (g *GameControls) onClickActionable(item actionableType) {
|
||||
|
||||
g.inventory.Toggle()
|
||||
g.updateLayout()
|
||||
case miniPanelSkillTree:
|
||||
log.Println("Skilltree button on mini panel is pressed")
|
||||
|
||||
g.skilltree.Toggle()
|
||||
g.updateLayout()
|
||||
case miniPanelGameMenu:
|
||||
g.miniPanel.Close()
|
||||
g.escapeMenu.open()
|
||||
|
@ -44,7 +44,7 @@ type StatsPanelLabels struct {
|
||||
type HeroStatsPanel struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
frame *d2ui.Sprite
|
||||
frame *d2ui.UIFrame
|
||||
panel *d2ui.Sprite
|
||||
heroState *d2hero.HeroStatsState
|
||||
heroName string
|
||||
@ -81,10 +81,7 @@ func NewHeroStatsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName
|
||||
func (s *HeroStatsPanel) Load() {
|
||||
var err error
|
||||
|
||||
s.frame, err = s.uiManager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
|
||||
|
||||
s.panel, err = s.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
@ -146,83 +143,9 @@ func (s *HeroStatsPanel) Render(target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
|
||||
|
||||
s.frame.Render(target)
|
||||
x, y := s.originX, s.originY
|
||||
|
||||
// Frame
|
||||
// Top left
|
||||
if err := s.frame.SetCurrentFrame(0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h := s.frame.GetCurrentFrameSize()
|
||||
|
||||
s.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
y += h
|
||||
|
||||
// Top right
|
||||
if err := s.frame.SetCurrentFrame(1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = s.frame.GetCurrentFrameSize()
|
||||
|
||||
s.frame.SetPosition(x, s.originY+h)
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x = s.originX
|
||||
|
||||
// Right
|
||||
if err := s.frame.SetCurrentFrame(2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = s.frame.GetCurrentFrameSize()
|
||||
s.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
y += h
|
||||
|
||||
// Bottom left
|
||||
if err := s.frame.SetCurrentFrame(3); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = s.frame.GetCurrentFrameSize()
|
||||
|
||||
s.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
|
||||
// Bottom right
|
||||
if err := s.frame.SetCurrentFrame(4); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, h = s.frame.GetCurrentFrameSize()
|
||||
|
||||
s.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x, y = s.originX, s.originY
|
||||
y += 64
|
||||
x += 80
|
||||
|
||||
@ -232,7 +155,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = s.panel.GetCurrentFrameSize()
|
||||
w, h := s.panel.GetCurrentFrameSize()
|
||||
|
||||
s.panel.SetPosition(x, y+h)
|
||||
|
||||
|
@ -3,7 +3,6 @@ package d2player
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
|
||||
|
||||
@ -21,7 +20,7 @@ type Inventory struct {
|
||||
asset *d2asset.AssetManager
|
||||
item *diablo2item.ItemFactory
|
||||
uiManager *d2ui.UIManager
|
||||
frame *d2ui.Sprite
|
||||
frame *d2ui.UIFrame
|
||||
panel *d2ui.Sprite
|
||||
grid *ItemGrid
|
||||
hoverLabel *d2ui.Label
|
||||
@ -77,12 +76,7 @@ func (g *Inventory) Close() {
|
||||
|
||||
// Load the resources required by the inventory
|
||||
func (g *Inventory) Load() {
|
||||
sprite, err := g.uiManager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
g.frame = sprite
|
||||
g.frame = d2ui.NewUIFrame(g.asset, g.uiManager, d2ui.FrameRight)
|
||||
|
||||
g.panel, _ = g.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
|
||||
@ -129,7 +123,7 @@ func (g *Inventory) Load() {
|
||||
}
|
||||
|
||||
// TODO: Load the player's actual items
|
||||
_, err = g.grid.Add(inventoryItems...)
|
||||
_, err := g.grid.Add(inventoryItems...)
|
||||
if err != nil {
|
||||
fmt.Printf("could not add items to the inventory, err: %v\n", err)
|
||||
}
|
||||
@ -141,84 +135,9 @@ func (g *Inventory) Render(target d2interface.Surface) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
x, y := g.originX, g.originY
|
||||
g.frame.Render(target)
|
||||
|
||||
// Frame
|
||||
// Top left
|
||||
if err := g.frame.SetCurrentFrame(5); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h := g.frame.GetCurrentFrameSize()
|
||||
|
||||
g.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := g.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
|
||||
// Top right
|
||||
if err := g.frame.SetCurrentFrame(6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = g.frame.GetCurrentFrameSize()
|
||||
|
||||
g.frame.SetPosition(x, y+h)
|
||||
|
||||
if err := g.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x += w
|
||||
y += h
|
||||
|
||||
// Right
|
||||
if err := g.frame.SetCurrentFrame(7); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = g.frame.GetCurrentFrameSize()
|
||||
|
||||
g.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := g.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
y += h
|
||||
|
||||
// Bottom right
|
||||
if err := g.frame.SetCurrentFrame(8); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = g.frame.GetCurrentFrameSize()
|
||||
|
||||
g.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := g.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x -= w
|
||||
|
||||
// Bottom left
|
||||
if err := g.frame.SetCurrentFrame(9); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = g.frame.GetCurrentFrameSize()
|
||||
|
||||
g.frame.SetPosition(x-w, y+h)
|
||||
|
||||
if err := g.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x, y = g.originX+1, g.originY
|
||||
x, y := g.originX+1, g.originY
|
||||
y += 64
|
||||
|
||||
// Panel
|
||||
@ -227,7 +146,7 @@ func (g *Inventory) Render(target d2interface.Surface) error {
|
||||
return err
|
||||
}
|
||||
|
||||
w, h = g.panel.GetCurrentFrameSize()
|
||||
w, h := g.panel.GetCurrentFrameSize()
|
||||
|
||||
g.panel.SetPosition(x, y+h)
|
||||
|
||||
|
415
d2game/d2player/skilltree.go
Normal file
415
d2game/d2player/skilltree.go
Normal file
@ -0,0 +1,415 @@
|
||||
package d2player
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||
)
|
||||
|
||||
const (
|
||||
TabButtonX = 628
|
||||
TabButton0Y = 385
|
||||
TabButton1Y = 277
|
||||
TabButton2Y = 170
|
||||
|
||||
AvailSPLabelX = 677
|
||||
AvailSPLabelY = 72
|
||||
|
||||
SkillIconXOff = 346
|
||||
SkillIconYOff = 59
|
||||
SkillIconDistX = 69
|
||||
SkillIconDistY = 68
|
||||
)
|
||||
|
||||
type SkillTreeTab struct {
|
||||
buttonText string
|
||||
button *d2ui.Button
|
||||
}
|
||||
|
||||
func (st *SkillTreeTab) CreateButton(uiManager *d2ui.UIManager, x int, y int) {
|
||||
st.button = uiManager.NewButton(d2ui.ButtonTypeSkillTreeTab, st.buttonText)
|
||||
st.button.SetVisible(false)
|
||||
st.button.SetPosition(x, y)
|
||||
}
|
||||
|
||||
type SkillTreeHeroTypeResources struct {
|
||||
skillIcon *d2ui.Sprite
|
||||
skillIconPath string
|
||||
skillPanel *d2ui.Sprite
|
||||
skillPanelPath string
|
||||
}
|
||||
|
||||
type SkillTree struct {
|
||||
resources *SkillTreeHeroTypeResources
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
guiManager *d2gui.GuiManager
|
||||
uiManager *d2ui.UIManager
|
||||
layout *d2gui.Layout
|
||||
skills map[int]*d2hero.HeroSkill
|
||||
heroClass d2enum.Hero
|
||||
frame *d2ui.UIFrame
|
||||
availSPLabel *d2ui.Label
|
||||
tab [3]*SkillTreeTab
|
||||
isOpen bool
|
||||
originX int
|
||||
originY int
|
||||
selectedTab int
|
||||
}
|
||||
|
||||
func NewSkillTree(
|
||||
skills map[int]*d2hero.HeroSkill,
|
||||
heroClass d2enum.Hero,
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
ui *d2ui.UIManager,
|
||||
guiManager *d2gui.GuiManager,
|
||||
) *SkillTree {
|
||||
st := &SkillTree {
|
||||
skills: skills,
|
||||
heroClass: heroClass,
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
uiManager: ui,
|
||||
guiManager: guiManager,
|
||||
originX: 401,
|
||||
originY: 64,
|
||||
tab: [3]*SkillTreeTab{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
},
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
func (s *SkillTree) Load() {
|
||||
|
||||
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameRight)
|
||||
|
||||
s.setHeroTypeResourcePath()
|
||||
s.LoadForHeroType()
|
||||
s.setTab(0)
|
||||
}
|
||||
|
||||
func (s *SkillTree) LoadForHeroType() {
|
||||
sp, err := s.uiManager.NewSprite(s.resources.skillPanelPath, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
s.resources.skillPanel = sp
|
||||
|
||||
si, err := s.uiManager.NewSprite(s.resources.skillIconPath, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
s.resources.skillIcon = si
|
||||
|
||||
s.tab[0].CreateButton(s.uiManager, TabButtonX, TabButton0Y)
|
||||
s.tab[0].button.OnActivated(func() { s.setTab(0) })
|
||||
s.tab[1].CreateButton(s.uiManager, TabButtonX, TabButton1Y)
|
||||
s.tab[1].button.OnActivated(func() { s.setTab(1) })
|
||||
s.tab[2].CreateButton(s.uiManager, TabButtonX, TabButton2Y)
|
||||
s.tab[2].button.OnActivated(func() { s.setTab(2) })
|
||||
|
||||
s.availSPLabel = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||
s.availSPLabel.SetPosition(AvailSPLabelX, AvailSPLabelY)
|
||||
s.availSPLabel.Alignment = d2gui.HorizontalAlignCenter
|
||||
s.availSPLabel.SetText(fmt.Sprintf("%s\n%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree1"),
|
||||
d2tbl.TranslateString("StrSklTree2"),
|
||||
d2tbl.TranslateString("StrSklTree3"),
|
||||
))
|
||||
}
|
||||
|
||||
func (s *SkillTree) setHeroTypeResourcePath() {
|
||||
var res *SkillTreeHeroTypeResources
|
||||
|
||||
switch s.heroClass {
|
||||
case d2enum.HeroBarbarian:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelBarbarian,
|
||||
skillIconPath: d2resource.BarbarianSkills,
|
||||
}
|
||||
|
||||
s.tab[0].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree21"),
|
||||
d2tbl.TranslateString("StrSklTree4"))
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree21"),
|
||||
d2tbl.TranslateString("StrSklTree22"))
|
||||
s.tab[2].buttonText = d2tbl.TranslateString("StrSklTree20")
|
||||
|
||||
case d2enum.HeroNecromancer:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelNecromancer,
|
||||
skillIconPath: d2resource.NecromancerSkills,
|
||||
}
|
||||
|
||||
s.tab[0].buttonText = d2tbl.TranslateString("StrSklTree19")
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree17"),
|
||||
d2tbl.TranslateString("StrSklTree18"),
|
||||
d2tbl.TranslateString("StrSklTree5"))
|
||||
s.tab[2].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree16"),
|
||||
d2tbl.TranslateString("StrSklTree5"))
|
||||
case d2enum.HeroPaladin:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelPaladin,
|
||||
skillIconPath: d2resource.PaladinSkills,
|
||||
}
|
||||
|
||||
s.tab[0].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree15"),
|
||||
d2tbl.TranslateString("StrSklTree4"))
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree14"),
|
||||
d2tbl.TranslateString("StrSklTree13"))
|
||||
s.tab[2].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree12"),
|
||||
d2tbl.TranslateString("StrSklTree13"))
|
||||
case d2enum.HeroAssassin:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelAssassin,
|
||||
skillIconPath: d2resource.AssassinSkills,
|
||||
}
|
||||
|
||||
s.tab[0].buttonText = d2tbl.TranslateString("StrSklTree30")
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree31"),
|
||||
d2tbl.TranslateString("StrSklTree32"))
|
||||
s.tab[2].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree33"),
|
||||
d2tbl.TranslateString("StrSklTree34"))
|
||||
case d2enum.HeroSorceress:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelSorcerer,
|
||||
skillIconPath: d2resource.SorcererSkills,
|
||||
}
|
||||
s.tab[0].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree25"),
|
||||
d2tbl.TranslateString("StrSklTree5"))
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree24"),
|
||||
d2tbl.TranslateString("StrSklTree5"))
|
||||
s.tab[2].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree23"),
|
||||
d2tbl.TranslateString("StrSklTree5"))
|
||||
case d2enum.HeroAmazon:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelAmazon,
|
||||
skillIconPath: d2resource.AmazonSkills,
|
||||
}
|
||||
s.tab[0].buttonText = fmt.Sprintf("%s\n%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree10"),
|
||||
d2tbl.TranslateString("StrSklTree11"),
|
||||
d2tbl.TranslateString("StrSklTree4"))
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree8"),
|
||||
d2tbl.TranslateString("StrSklTree9"),
|
||||
d2tbl.TranslateString("StrSklTree4"))
|
||||
s.tab[2].buttonText = fmt.Sprintf("%s\n%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree6"),
|
||||
d2tbl.TranslateString("StrSklTree7"),
|
||||
d2tbl.TranslateString("StrSklTree4"))
|
||||
case d2enum.HeroDruid:
|
||||
res = &SkillTreeHeroTypeResources {
|
||||
skillPanelPath: d2resource.SkillsPanelDruid,
|
||||
skillIconPath: d2resource.DruidSkills,
|
||||
}
|
||||
s.tab[0].buttonText = d2tbl.TranslateString("StrSklTree26")
|
||||
s.tab[1].buttonText = fmt.Sprintf("%s\n%s",
|
||||
d2tbl.TranslateString("StrSklTree27"),
|
||||
d2tbl.TranslateString("StrSklTree28"))
|
||||
s.tab[2].buttonText = d2tbl.TranslateString("StrSklTree29")
|
||||
default:
|
||||
log.Fatal("Unknown Hero Type")
|
||||
}
|
||||
s.resources = res
|
||||
}
|
||||
|
||||
func (s *SkillTree) Toggle() {
|
||||
fmt.Println("SkillTree toggled")
|
||||
if s.isOpen {
|
||||
s.Close()
|
||||
} else {
|
||||
s.Open()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkillTree) Close() {
|
||||
s.isOpen = false
|
||||
s.guiManager.SetLayout(nil)
|
||||
for i:=0; i < 3; i++ {
|
||||
s.tab[i].button.SetVisible(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkillTree) Open() {
|
||||
s.isOpen = true
|
||||
if s.layout == nil {
|
||||
s.layout = d2gui.CreateLayout(s.renderer, d2gui.PositionTypeHorizontal, s.asset)
|
||||
}
|
||||
|
||||
for i:=0; i < 3; i++ {
|
||||
s.tab[i].button.SetVisible(true)
|
||||
}
|
||||
s.guiManager.SetLayout(s.layout)
|
||||
|
||||
}
|
||||
|
||||
func (s *SkillTree) IsOpen() bool {
|
||||
return s.isOpen
|
||||
}
|
||||
|
||||
func (s *SkillTree) setTab(tab int) {
|
||||
s.selectedTab = tab
|
||||
}
|
||||
|
||||
func (s *SkillTree) renderPanelSegment(
|
||||
target d2interface.Surface,
|
||||
frame int) error {
|
||||
if err := s.resources.skillPanel.SetCurrentFrame(frame); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.resources.skillPanel.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SkillTree) renderTabCommon (target d2interface.Surface) error {
|
||||
skillPanel := s.resources.skillPanel
|
||||
x, y := s.originX, s.originY
|
||||
|
||||
// top
|
||||
w, h, err := skillPanel.GetFrameSize(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
y += h
|
||||
skillPanel.SetPosition(x, y)
|
||||
if err:= s.renderPanelSegment(target, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
skillPanel.SetPosition(x+w, y)
|
||||
if err:= s.renderPanelSegment(target, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// bottom
|
||||
_, h, err = skillPanel.GetFrameSize(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
y += h
|
||||
skillPanel.SetPosition(x, y)
|
||||
if err:= s.renderPanelSegment(target, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
skillPanel.SetPosition(x+w, y)
|
||||
if err:= s.renderPanelSegment(target, 3); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// available skill points label
|
||||
s.availSPLabel.Render(target)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SkillTree) renderTab (target d2interface.Surface, tab int) error {
|
||||
var frameID [2]int
|
||||
|
||||
frameID[0] = 4 + (4*tab)
|
||||
frameID[1] = 6 + (4*tab)
|
||||
|
||||
skillPanel := s.resources.skillPanel
|
||||
x, y := s.originX, s.originY
|
||||
|
||||
// top
|
||||
_, h0, err := skillPanel.GetFrameSize(frameID[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
y += h0
|
||||
skillPanel.SetPosition(x, y)
|
||||
if err:= s.renderPanelSegment(target, frameID[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// bottom
|
||||
w, h1, err := skillPanel.GetFrameSize(frameID[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skillPanel.SetPosition(x, y+h1)
|
||||
if err:= s.renderPanelSegment(target, frameID[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// tab button highlighted
|
||||
switch tab {
|
||||
case 0:
|
||||
skillPanel.SetPosition(x+w, y+h1)
|
||||
if err:= s.renderPanelSegment(target, 7); err != nil {
|
||||
return err
|
||||
}
|
||||
case 1:
|
||||
x += w
|
||||
skillPanel.SetPosition(x, s.originY + h0)
|
||||
if err:= s.renderPanelSegment(target, 9); err != nil {
|
||||
return err
|
||||
}
|
||||
skillPanel.SetPosition(x, y + h1)
|
||||
if err:= s.renderPanelSegment(target, 11); err != nil {
|
||||
return err
|
||||
}
|
||||
case 2:
|
||||
skillPanel.SetPosition(x+w, y)
|
||||
if err:= s.renderPanelSegment(target, 13); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SkillTree) renderSkillIcons(target d2interface.Surface, tab int) error {
|
||||
|
||||
skillIcon := s.resources.skillIcon
|
||||
for idx:=range s.skills {
|
||||
skill := s.skills[idx]
|
||||
if skill.SkillPage != tab + 1 {
|
||||
continue
|
||||
}
|
||||
if err := skillIcon.SetCurrentFrame(skill.IconCel); err != nil {
|
||||
return err
|
||||
}
|
||||
skillIcon.SetPosition(SkillIconXOff + skill.SkillColumn * SkillIconDistX, SkillIconYOff + skill.SkillRow * SkillIconDistY)
|
||||
if err := skillIcon.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
func (s *SkillTree) Render (target d2interface.Surface) error {
|
||||
if !s.isOpen {
|
||||
return nil
|
||||
}
|
||||
s.frame.Render(target)
|
||||
s.renderTabCommon(target)
|
||||
s.renderTab(target, s.selectedTab)
|
||||
s.renderSkillIcons(target, s.selectedTab)
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user