1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-12-25 11:36:26 -05:00

Merge pull request #975 from gucio321/add-skill-buttons

Add-skill buttons
This commit is contained in:
Tim Sarbin 2020-12-16 18:41:28 -05:00 committed by GitHub
commit 27270e7d98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 231 additions and 73 deletions

View File

@ -243,16 +243,18 @@ const (
MinipanelSmall = "/data/global/ui/PANEL/minipanel_s.dc6"
MinipanelButton = "/data/global/ui/PANEL/minipanelbtn.DC6"
Frame = "/data/global/ui/PANEL/800borderframe.dc6"
InventoryCharacterPanel = "/data/global/ui/PANEL/invchar6.DC6"
InventoryWeaponsTab = "/data/global/ui/PANEL/invchar6Tab.DC6"
SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6"
SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6"
SkillsPanelDruid = "/data/global/ui/SPELLS/skltree_d_back.DC6"
SkillsPanelAssassin = "/data/global/ui/SPELLS/skltree_i_back.DC6"
SkillsPanelNecromancer = "/data/global/ui/SPELLS/skltree_n_back.DC6"
SkillsPanelPaladin = "/data/global/ui/SPELLS/skltree_p_back.DC6"
SkillsPanelSorcerer = "/data/global/ui/SPELLS/skltree_s_back.DC6"
Frame = "/data/global/ui/PANEL/800borderframe.dc6"
InventoryCharacterPanel = "/data/global/ui/PANEL/invchar6.DC6"
HeroStatsPanelStatsPoints = "/data/global/ui/PANEL/skillpoints.dc6"
HeroStatsPanelSocket = "/data/global/ui/PANEL/levelsocket.dc6"
InventoryWeaponsTab = "/data/global/ui/PANEL/invchar6Tab.DC6"
SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6"
SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6"
SkillsPanelDruid = "/data/global/ui/SPELLS/skltree_d_back.DC6"
SkillsPanelAssassin = "/data/global/ui/SPELLS/skltree_i_back.DC6"
SkillsPanelNecromancer = "/data/global/ui/SPELLS/skltree_n_back.DC6"
SkillsPanelPaladin = "/data/global/ui/SPELLS/skltree_p_back.DC6"
SkillsPanelSorcerer = "/data/global/ui/SPELLS/skltree_s_back.DC6"
GenericSkills = "/data/global/ui/SPELLS/Skillicon.DC6"
AmazonSkills = "/data/global/ui/SPELLS/AmSkillicon.DC6"

View File

@ -10,28 +10,23 @@ type HeroStatsState struct {
Level int `json:"level"`
Experience int `json:"experience"`
Vitality int `json:"vitality"`
Energy int `json:"energy"`
Strength int `json:"strength"`
Energy int `json:"energy"`
Dexterity int `json:"dexterity"`
Vitality int `json:"vitality"`
// there are stats and skills points remaining to add.
StatsPoints int `json:"statsPoints"`
SkillPoints int `json:"skillPoints"`
AttackRating int `json:"attackRating"`
DefenseRating int `json:"defenseRating"`
MaxStamina int `json:"maxStamina"`
Health int `json:"health"`
MaxHealth int `json:"maxHealth"`
Mana int `json:"mana"`
MaxMana int `json:"maxMana"`
FireResistance int `json:"fireResistance"`
ColdResistance int `json:"coldResistance"`
LightningResistance int `json:"lightningResistance"`
PoisonResistance int `json:"poisonResistance"`
Health int `json:"health"`
MaxHealth int `json:"maxHealth"`
Mana int `json:"mana"`
MaxMana int `json:"maxMana"`
Stamina float64 `json:"-"` // only MaxStamina is saved, Stamina gets reset on entering world
MaxStamina int `json:"maxStamina"`
// values which are not saved/loaded(computed)
Stamina float64 `json:"-"` // only MaxStamina is saved, Stamina gets reset on entering world
NextLevelExp int `json:"-"`
NextLevelExp int `json:"-"`
}
// CreateHeroStatsState generates a running state from a hero stats.
@ -44,6 +39,8 @@ func (f *HeroStateFactory) CreateHeroStatsState(heroClass d2enum.Hero, classStat
Dexterity: classStats.InitDex,
Vitality: classStats.InitVit,
Energy: classStats.InitEne,
StatsPoints: 0,
SkillPoints: 0,
MaxHealth: classStats.InitVit * classStats.LifePerVit,
MaxMana: classStats.InitEne * classStats.ManaPerEne,

View File

@ -55,6 +55,7 @@ const (
ButtonTypeSquelchChat ButtonType = 35
ButtonTypeTabBlank ButtonType = 36
ButtonTypeBlankQuestBtn ButtonType = 37
ButtonTypeAddSkill ButtonType = 38
ButtonNoFixedWidth int = -1
ButtonNoFixedHeight int = -1
@ -199,6 +200,10 @@ const (
buttonGoldCoinSegmentsY = 1
buttonGoldCoinDisabledFrame = -1
buttonAddSkillSegmentsX = 1
buttonAddSkillSegmentsY = 1
buttonAddSkillDisabledFrame = 2
pressedButtonOffset = 2
)
@ -746,6 +751,20 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
FixedHeight: ButtonNoFixedHeight,
LabelColor: whiteAlpha100,
},
ButtonTypeAddSkill: {
XSegments: buttonAddSkillSegmentsX,
YSegments: buttonAddSkillSegmentsY,
DisabledFrame: buttonAddSkillDisabledFrame,
DisabledColor: whiteAlpha100,
ResourceName: d2resource.AddSkillButton,
PaletteName: d2resource.PaletteSky,
Toggleable: true,
FontPath: d2resource.Font16,
AllowFrameChange: true,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
},
}
}

View File

@ -398,25 +398,15 @@ func (m *EscapeMenu) OnLoad() {
// OnEscKey is called when the escape key is pressed
func (m *EscapeMenu) OnEscKey() {
// note: original D2 returns straight to the game from however deep in the menu we are
switch m.currentLayout {
case optionsLayoutID:
m.setLayout(mainLayoutID)
return
case soundOptionsLayoutID,
videoOptionsLayoutID,
automapOptionsLayoutID,
configureControlsLayoutID:
if m.currentLayout == configureControlsLayoutID {
m.setLayout(optionsLayoutID)
if err := m.keyBindingMenu.Close(); err != nil {
m.Errorf("unable to close the configure controls menu: %v", err.Error())
}
return
} else {
m.close()
}
m.close()
}
// SetOnCloseCb sets the callback that is run when close() is called

View File

@ -214,7 +214,7 @@ func NewGameControls(
return nil, err
}
skilltree := newSkillTree(hero.Skills, hero.Class, asset, l, ui)
skilltree := newSkillTree(hero.Skills, hero.Class, hero.Stats, asset, l, ui)
miniPanel := newMiniPanel(asset, ui, l, isSinglePlayer)
@ -224,13 +224,9 @@ func NewGameControls(
}
helpOverlay := NewHelpOverlay(asset, ui, l, keyMap)
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, mapRenderer)
const blackAlpha50percent = 0x0000007f
hoverLabel := hud.nameLabel
hoverLabel.SetBackgroundColor(d2util.Color(blackAlpha50percent))
gc := &GameControls{
asset: asset,
ui: ui,
@ -246,7 +242,6 @@ func NewGameControls(
questLog: questLog,
HelpOverlay: helpOverlay,
keyMap: keyMap,
hud: hud,
bottomMenuRect: &d2geom.Rectangle{
Left: menuBottomRectX,
Top: menuBottomRectY,
@ -271,6 +266,12 @@ func NewGameControls(
isSinglePlayer: isSinglePlayer,
}
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, gc, mapRenderer)
gc.hud = hud
hoverLabel := hud.nameLabel
hoverLabel.SetBackgroundColor(d2util.Color(blackAlpha50percent))
gc.heroStatsPanel.SetOnCloseCb(gc.onCloseHeroStatsPanel)
gc.questLog.SetOnCloseCb(gc.onCloseQuestLog)
gc.inventory.SetOnCloseCb(gc.onCloseInventory)
@ -713,6 +714,9 @@ func (g *GameControls) Load() {
g.questLog.Load()
g.HelpOverlay.Load()
g.loadAddButtons()
g.setAddButtons()
miniPanelActions := &miniPanelActions{
characterToggle: g.toggleHeroStatsPanel,
inventoryToggle: g.toggleInventoryPanel,
@ -733,6 +737,10 @@ func (g *GameControls) Advance(elapsed float64) error {
return err
}
if g.heroStatsPanel.IsOpen() || g.skilltree.IsOpen() {
g.setAddButtons()
}
return nil
}
@ -1099,3 +1107,13 @@ func (g *GameControls) bindTerminalCommands(term d2interface.Terminal) error {
return nil
}
func (g *GameControls) setAddButtons() {
g.hud.addStatsButton.SetEnabled(g.hero.Stats.StatsPoints > 0)
g.hud.addSkillButton.SetEnabled(g.hero.Stats.SkillPoints > 0)
}
func (g *GameControls) loadAddButtons() {
g.hud.addStatsButton.OnActivated(func() { g.toggleHeroStatsPanel() })
g.hud.addSkillButton.OnActivated(func() { g.toggleSkilltreePanel() })
}

View File

@ -9,6 +9,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
@ -55,6 +56,15 @@ const (
const (
heroStatsCloseButtonX, heroStatsCloseButtonY = 208, 453
addStatSocketOffsetX, addStatSocketOffsetY = -3, 34
)
const (
newStatsRemainingPointsFieldX, newStatsRemainingPointsFieldY = 83, 430
newStatsRemainingPointsLabelX = 92
newStatsRemainingPointsLabel1Y = 411
newStatsRemainingPointsLabel2Y = 418
newStatsRemainingPointsValueX, newStatsRemainingPointsValueY = 188, 411
)
// PanelText represents text on the panel
@ -113,15 +123,17 @@ func NewHeroStatsPanel(asset *d2asset.AssetManager,
// HeroStatsPanel represents the hero status panel
type HeroStatsPanel struct {
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
panel *d2ui.Sprite
heroState *d2hero.HeroStatsState
heroName string
heroClass d2enum.Hero
labels *StatsPanelLabels
onCloseCb func()
panelGroup *d2ui.WidgetGroup
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
panel *d2ui.Sprite
heroState *d2hero.HeroStatsState
heroName string
heroClass d2enum.Hero
labels *StatsPanelLabels
onCloseCb func()
panelGroup *d2ui.WidgetGroup
newStatPoints *d2ui.WidgetGroup
remainingPoints *d2ui.Label
originX int
originY int
@ -135,6 +147,7 @@ func (s *HeroStatsPanel) Load() {
var err error
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
s.newStatPoints = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
s.panelGroup.AddWidget(frame)
@ -154,10 +167,91 @@ func (s *HeroStatsPanel) Load() {
closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(closeButton)
s.loadNewStatPoints()
s.setLayout()
s.initStatValueLabels()
s.panelGroup.SetVisible(false)
}
func (s *HeroStatsPanel) loadNewStatPoints() {
field, err := s.uiManager.NewSprite(d2resource.HeroStatsPanelStatsPoints, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
field.SetPosition(newStatsRemainingPointsFieldX, newStatsRemainingPointsFieldY)
s.newStatPoints.AddWidget(field)
label1 := s.uiManager.NewLabel(d2resource.Font6, d2resource.PaletteSky)
label1.SetPosition(newStatsRemainingPointsLabelX, newStatsRemainingPointsLabel1Y)
label1.SetText(s.asset.TranslateString("strchrstat"))
label1.Color[0] = d2util.Color(d2gui.ColorRed)
s.newStatPoints.AddWidget(label1)
label2 := s.uiManager.NewLabel(d2resource.Font6, d2resource.PaletteSky)
label2.SetPosition(newStatsRemainingPointsLabelX, newStatsRemainingPointsLabel2Y)
label2.SetText(s.asset.TranslateString("strchrrema"))
label2.Color[0] = d2util.Color(d2gui.ColorRed)
s.newStatPoints.AddWidget(label2)
s.remainingPoints = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
s.remainingPoints.SetText(strconv.Itoa(s.heroState.StatsPoints))
s.remainingPoints.SetPosition(newStatsRemainingPointsValueX, newStatsRemainingPointsValueY)
s.remainingPoints.Alignment = d2ui.HorizontalAlignCenter
s.newStatPoints.AddWidget(s.remainingPoints)
buttons := []struct {
x int
y int
cb func()
}{
{205, 140, func() {
s.heroState.Strength++
}},
{205, 201, func() {
s.heroState.Dexterity++
}},
{205, 286, func() {
s.heroState.Vitality++
}},
{205, 347, func() {
s.heroState.Energy++
}},
}
var socket *d2ui.Sprite
var button *d2ui.Button
for _, i := range buttons {
currentValue := i
socket, err = s.uiManager.NewSprite(d2resource.HeroStatsPanelSocket, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
socket.SetPosition(i.x+addStatSocketOffsetX, i.y+addStatSocketOffsetY)
s.newStatPoints.AddWidget(socket)
button = s.uiManager.NewButton(d2ui.ButtonTypeAddSkill, d2resource.PaletteSky)
button.SetPosition(i.x, i.y)
button.OnActivated(func() {
currentValue.cb()
s.heroState.StatsPoints--
s.remainingPoints.SetText(strconv.Itoa(s.heroState.StatsPoints))
s.setStatValues()
s.setLayout()
})
s.newStatPoints.AddWidget(button)
}
}
func (s *HeroStatsPanel) setLayout() {
s.newStatPoints.SetVisible(s.heroState.StatsPoints > 0 && s.IsOpen())
}
// IsOpen returns true if the hero status panel is open
func (s *HeroStatsPanel) IsOpen() bool {
return s.isOpen
@ -176,12 +270,14 @@ func (s *HeroStatsPanel) Toggle() {
func (s *HeroStatsPanel) Open() {
s.isOpen = true
s.panelGroup.SetVisible(true)
s.setLayout()
}
// Close closed the hero status panel
func (s *HeroStatsPanel) Close() {
s.isOpen = false
s.panelGroup.SetVisible(false)
s.setLayout()
s.onCloseCb()
}

View File

@ -70,6 +70,11 @@ const (
whiteAlpha100 = 0xffffffff
)
const (
addStatsButtonX, addStatsButtonY = 206, 561
addSkillButtonX, addSkillButtonY = 563, 561
)
// HUD represents the always visible user interface of the game
type HUD struct {
actionableRegions []actionableRegion
@ -103,7 +108,11 @@ type HUD struct {
widgetLeftSkill *d2ui.CustomWidget
widgetRightSkill *d2ui.CustomWidget
panelBackground *d2ui.CustomWidget
addStatsButton *d2ui.Button
addSkillButton *d2ui.Button
panelGroup *d2ui.WidgetGroup
gameControls *GameControls
*d2util.Logger
}
@ -116,6 +125,7 @@ func NewHUD(
actionableRegions []actionableRegion,
mapEngine *d2mapengine.MapEngine,
l d2util.LogLevel,
gameControls *GameControls,
mapRenderer *d2maprenderer.MapRenderer,
) *HUD {
nameLabel := ui.NewLabel(d2resource.Font16, d2resource.PaletteStatic)
@ -149,6 +159,7 @@ func NewHUD(
zoneChangeText: zoneLabel,
healthGlobe: healthGlobe,
manaGlobe: manaGlobe,
gameControls: gameControls,
}
hud.Logger = d2util.NewLogger()
@ -177,6 +188,16 @@ func (h *HUD) Load() {
h.loadCustomWidgets()
h.loadUIButtons()
h.addStatsButton = h.uiManager.NewButton(d2ui.ButtonTypeAddSkill, "")
h.addStatsButton.SetPosition(addStatsButtonX, addStatsButtonY)
h.addStatsButton.SetVisible(false)
h.panelGroup.AddWidget(h.addStatsButton)
h.addSkillButton = h.uiManager.NewButton(d2ui.ButtonTypeAddSkill, "")
h.addSkillButton.SetPosition(addSkillButtonX, addSkillButtonY)
h.addSkillButton.SetVisible(false)
h.panelGroup.AddWidget(h.addSkillButton)
h.panelGroup.SetVisible(true)
}

View File

@ -3,6 +3,7 @@ package d2player
import (
"errors"
"fmt"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -56,6 +57,10 @@ const (
frameSelectedTab3Full = 13
)
const (
remainingPointsLabelX, remainingPointsLabelY = 677, 128
)
const (
skillTreePanelX = 401
skillTreePanelY = 64
@ -87,6 +92,7 @@ type skillTreeHeroTypeResources struct {
func newSkillTree(
skills map[int]*d2hero.HeroSkill,
heroClass d2enum.Hero,
hero *d2hero.HeroStatsState,
asset *d2asset.AssetManager,
l d2util.LogLevel,
ui *d2ui.UIManager,
@ -98,6 +104,7 @@ func newSkillTree(
uiManager: ui,
originX: skillTreePanelX,
originY: skillTreePanelY,
stats: hero,
tab: [numTabs]*skillTreeTab{
{},
{},
@ -114,24 +121,26 @@ func newSkillTree(
}
type skillTree struct {
resources *skillTreeHeroTypeResources
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
skills map[int]*d2hero.HeroSkill
skillIcons []*skillIcon
heroClass d2enum.Hero
frame *d2ui.UIFrame
availSPLabel *d2ui.Label
closeButton *d2ui.Button
tab [numTabs]*skillTreeTab
isOpen bool
originX int
originY int
selectedTab int
onCloseCb func()
panelGroup *d2ui.WidgetGroup
iconGroup *d2ui.WidgetGroup
panel *d2ui.CustomWidget
resources *skillTreeHeroTypeResources
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
skills map[int]*d2hero.HeroSkill
skillIcons []*skillIcon
heroClass d2enum.Hero
frame *d2ui.UIFrame
availSPLabel *d2ui.Label
closeButton *d2ui.Button
tab [numTabs]*skillTreeTab
remainingPoints *d2ui.Label
isOpen bool
originX int
originY int
selectedTab int
onCloseCb func()
panelGroup *d2ui.WidgetGroup
iconGroup *d2ui.WidgetGroup
panel *d2ui.CustomWidget
stats *d2hero.HeroStatsState
*d2util.Logger
l d2util.LogLevel
@ -152,6 +161,12 @@ func (s *skillTree) load() {
s.closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(s.closeButton)
s.remainingPoints = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
s.remainingPoints.SetPosition(remainingPointsLabelX, remainingPointsLabelY)
s.remainingPoints.Alignment = d2ui.HorizontalAlignCenter
s.remainingPoints.SetText(strconv.Itoa(s.stats.SkillPoints))
s.panelGroup.AddWidget(s.remainingPoints)
if err := s.setHeroTypeResourcePath(); err != nil {
s.Error(err.Error())
}