mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-06-09 01:10:43 +00:00
Lint cleanup funlen (#854)
* d2ui/button.go: refactored button state prerender to fix funlen lint error * d2player/help/help.go: break up Load method to reduce complexity * d2game/d2player/game_controls.go: refactored renderHUD method, fixed funlen lint error * d2player/skilltree.go: fixed funlen lint error * map_engine_test.go: fixed funlen lint error
This commit is contained in:
parent
7d5cd10850
commit
33368e5aa3
|
@ -47,6 +47,12 @@ const (
|
||||||
ButtonNoFixedHeight int = -1
|
ButtonNoFixedHeight int = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
buttonStatePressed = iota + 1
|
||||||
|
buttonStateToggled
|
||||||
|
buttonStatePressedToggled
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
closeButtonBaseFrame = 10 // base frame offset of the "close" button dc6
|
closeButtonBaseFrame = 10 // base frame offset of the "close" button dc6
|
||||||
)
|
)
|
||||||
|
@ -315,21 +321,28 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
||||||
buttonSprite.SetPosition(0, 0)
|
buttonSprite.SetPosition(0, 0)
|
||||||
buttonSprite.SetEffect(d2enum.DrawEffectModulate)
|
buttonSprite.SetEffect(d2enum.DrawEffectModulate)
|
||||||
|
|
||||||
ui.addWidget(btn) // important that this comes before renderFrames!
|
ui.addWidget(btn) // important that this comes before prerenderStates!
|
||||||
|
|
||||||
btn.renderFrames(buttonSprite, &buttonLayout, lbl)
|
btn.prerenderStates(buttonSprite, &buttonLayout, lbl)
|
||||||
|
|
||||||
return btn
|
return btn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Button) renderFrames(btnSprite *Sprite, btnLayout *ButtonLayout, label *Label) {
|
type buttonStateDescriptor struct {
|
||||||
|
baseFrame int
|
||||||
|
offsetX, offsetY int
|
||||||
|
prerenderdestination *d2interface.Surface
|
||||||
|
fmtErr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, label *Label) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
totalButtonTypes := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments)
|
numButtonStates := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments)
|
||||||
|
|
||||||
|
// buttons always have a base image
|
||||||
if v.buttonLayout.HasImage {
|
if v.buttonLayout.HasImage {
|
||||||
err = btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame)
|
err = btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to render button normalSurface, err: %v\n", err)
|
fmt.Printf("failed to render button normalSurface, err: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -342,89 +355,82 @@ func (v *Button) renderFrames(btnSprite *Sprite, btnLayout *ButtonLayout, label
|
||||||
label.SetPosition(xOffset, textY)
|
label.SetPosition(xOffset, textY)
|
||||||
label.Render(v.normalSurface)
|
label.Render(v.normalSurface)
|
||||||
|
|
||||||
if btnLayout.HasImage && btnLayout.AllowFrameChange {
|
if !btnLayout.HasImage || !btnLayout.AllowFrameChange {
|
||||||
frameOffset := 0
|
return
|
||||||
xSeg, ySeg, baseFrame := btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame
|
}
|
||||||
|
|
||||||
totalButtonTypes--
|
xSeg, ySeg, baseFrame := btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame
|
||||||
if totalButtonTypes > 0 { // button has more than one type
|
|
||||||
frameOffset++
|
|
||||||
|
|
||||||
v.pressedSurface, err = v.manager.renderer.NewSurface(v.width, v.height,
|
buttonStateConfigs := make([]*buttonStateDescriptor, 0)
|
||||||
d2enum.FilterNearest)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = btnSprite.RenderSegmented(v.pressedSurface, xSeg, ySeg, baseFrame+frameOffset)
|
// pressed button
|
||||||
if err != nil {
|
if numButtonStates >= buttonStatePressed {
|
||||||
fmt.Printf("failed to render button pressedSurface, err: %v\n", err)
|
state := &buttonStateDescriptor{
|
||||||
}
|
baseFrame + buttonStatePressed,
|
||||||
|
xOffset - pressedButtonOffset, textY + pressedButtonOffset,
|
||||||
label.SetPosition(xOffset-pressedButtonOffset, textY+pressedButtonOffset)
|
&v.pressedSurface,
|
||||||
label.Render(v.pressedSurface)
|
"failed to render button pressedSurface, err: %v\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
if btnLayout.ResourceName == d2resource.BuySellButton {
|
buttonStateConfigs = append(buttonStateConfigs, state)
|
||||||
// Without returning early, the button UI gets all subsequent (unrelated) frames stacked on top
|
}
|
||||||
// Only 2 frames from this sprite are applicable to the button in question
|
|
||||||
// The presentation is incorrect without this hack
|
// toggle button
|
||||||
return
|
if numButtonStates >= buttonStateToggled {
|
||||||
|
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
|
||||||
|
baseFrame + buttonStateToggled,
|
||||||
|
xOffset, textY,
|
||||||
|
&v.toggledSurface,
|
||||||
|
"failed to render button toggledSurface, err: %v\n",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// pressed+toggled
|
||||||
|
if numButtonStates >= buttonStatePressedToggled {
|
||||||
|
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
|
||||||
|
baseFrame + buttonStatePressedToggled,
|
||||||
|
xOffset, textY,
|
||||||
|
&v.pressedToggledSurface,
|
||||||
|
"failed to render button pressedToggledSurface, err: %v\n",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// disabled button
|
||||||
|
if btnLayout.DisabledFrame != -1 {
|
||||||
|
disabledState := &buttonStateDescriptor{
|
||||||
|
btnLayout.DisabledFrame,
|
||||||
|
xOffset, textY,
|
||||||
|
&v.disabledSurface,
|
||||||
|
"failed to render button disabledSurface, err: %v\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
totalButtonTypes--
|
buttonStateConfigs = append(buttonStateConfigs, disabledState)
|
||||||
if totalButtonTypes > 0 { // button has more than two types
|
}
|
||||||
frameOffset++
|
|
||||||
|
|
||||||
v.toggledSurface, err = v.manager.renderer.NewSurface(v.width, v.height,
|
for stateIdx, w, h := 0, v.width, v.height; stateIdx < len(buttonStateConfigs); stateIdx++ {
|
||||||
d2enum.FilterNearest)
|
state := buttonStateConfigs[stateIdx]
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = btnSprite.RenderSegmented(v.toggledSurface, xSeg, ySeg, baseFrame+frameOffset)
|
if stateIdx >= 2 && btnLayout.ResourceName == d2resource.BuySellButton {
|
||||||
if err != nil {
|
// Without returning early, the button UI gets all subsequent (unrelated) frames
|
||||||
fmt.Printf("failed to render button toggledSurface, err: %v\n", err)
|
// stacked on top. Only 2 frames from this sprite are applicable to the button
|
||||||
}
|
// in question. The presentation is incorrect without this hack!
|
||||||
|
continue
|
||||||
label.SetPosition(xOffset, textY)
|
|
||||||
label.Render(v.toggledSurface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
totalButtonTypes--
|
surface, err := v.manager.renderer.NewSurface(w, h, d2enum.FilterNearest)
|
||||||
if totalButtonTypes > 0 { // button has more than three types
|
if err != nil {
|
||||||
frameOffset++
|
log.Print(err)
|
||||||
|
|
||||||
v.pressedToggledSurface, err = v.manager.renderer.NewSurface(v.width, v.height,
|
|
||||||
d2enum.FilterNearest)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = btnSprite.RenderSegmented(v.pressedSurface, xSeg, ySeg, baseFrame+frameOffset)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("failed to render button pressedToggledSurface, err: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
label.SetPosition(xOffset, textY)
|
|
||||||
label.Render(v.pressedToggledSurface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if btnLayout.DisabledFrame != -1 {
|
*state.prerenderdestination = surface
|
||||||
v.disabledSurface, err = v.manager.renderer.NewSurface(v.width, v.height,
|
|
||||||
d2enum.FilterNearest)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = btnSprite.RenderSegmented(v.disabledSurface, xSeg, ySeg, btnLayout.DisabledFrame)
|
err = btnSprite.RenderSegmented(*state.prerenderdestination, xSeg, ySeg, state.baseFrame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to render button disabledSurface, err: %v\n", err)
|
fmt.Printf(state.fmtErr, err)
|
||||||
}
|
|
||||||
|
|
||||||
label.SetPosition(xOffset, textY)
|
|
||||||
label.Render(v.disabledSurface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.SetPosition(state.offsetX, state.offsetY)
|
||||||
|
label.Render(*state.prerenderdestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -522,12 +522,8 @@ func (v *MainMenu) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnKeyUp is called when a key is released
|
// OnKeyUp is called when a key is released
|
||||||
func (v *MainMenu) OnKeyUp(event d2interface.KeyEvent) bool {
|
func (v *MainMenu) OnKeyUp(_ d2interface.KeyEvent) bool {
|
||||||
/*
|
// On retail version of D2, any key event puts you onto the main menu.
|
||||||
On retail version of D2 any key event puts you onto the main menu, so this is a supplement to that code up there
|
|
||||||
on line 515.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if v.screenMode == ScreenModeTrademark {
|
if v.screenMode == ScreenModeTrademark {
|
||||||
v.SetScreenMode(ScreenModeMainMenu)
|
v.SetScreenMode(ScreenModeMainMenu)
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -265,6 +265,14 @@ func (met *MapEngineTest) Render(screen d2interface.Surface) error {
|
||||||
screen.PushTranslation(0, lineNormalOffsetY)
|
screen.PushTranslation(0, lineNormalOffsetY)
|
||||||
defer screen.Pop()
|
defer screen.Pop()
|
||||||
|
|
||||||
|
if err := met.renderTileInfo(screen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (met *MapEngineTest) renderTileInfo(screen d2interface.Surface) error {
|
||||||
if met.selectedTile == nil {
|
if met.selectedTile == nil {
|
||||||
screen.PushTranslation(lineNormalIndentX, lineNormalOffsetY)
|
screen.PushTranslation(lineNormalIndentX, lineNormalOffsetY)
|
||||||
defer screen.Pop()
|
defer screen.Pop()
|
||||||
|
|
|
@ -161,6 +161,8 @@ const (
|
||||||
|
|
||||||
manaLabelX = 785
|
manaLabelX = 785
|
||||||
manaLabelY = 487
|
manaLabelY = 487
|
||||||
|
|
||||||
|
staminaExperienceY = 535
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -978,24 +980,139 @@ func (g *GameControls) renderPanels(target d2interface.Surface) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
mx, my := g.lastMouseX, g.lastMouseY
|
if err := g.renderGameControlPanelElements(target); err != nil {
|
||||||
width, height := target.GetSize()
|
return err
|
||||||
offsetX := 0
|
}
|
||||||
|
|
||||||
// Left globe holder
|
if err := g.HelpOverlay.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.isZoneTextShown {
|
||||||
|
g.zoneChangeText.SetPosition(zoneChangeTextX, zoneChangeTextY)
|
||||||
|
g.zoneChangeText.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.renderHealthTooltip(target)
|
||||||
|
g.renderManaTooltip(target)
|
||||||
|
g.renderRunWalkTooltip(target)
|
||||||
|
g.renderStaminaTooltip(target)
|
||||||
|
g.renderExperienceTooltip(target)
|
||||||
|
|
||||||
|
if g.skillSelectMenu.IsOpen() {
|
||||||
|
g.skillSelectMenu.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: the positioning of all of the panel elements is coupled to the rendering order :(
|
||||||
|
// don't change the order in which the render methods are called, as there is an x,y offset
|
||||||
|
// that is updated between render calls
|
||||||
|
func (g *GameControls) renderGameControlPanelElements(target d2interface.Surface) error {
|
||||||
|
_, height := target.GetSize()
|
||||||
|
offsetX, offsetY := 0, 0
|
||||||
|
|
||||||
|
// Main panel background
|
||||||
|
offsetY = height
|
||||||
|
if err := g.renderPanel(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Health globe
|
||||||
|
w, _ := g.mainPanel.GetCurrentFrameSize()
|
||||||
|
|
||||||
|
if err := g.renderHealthGlobe(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left Skill
|
||||||
|
offsetX += w
|
||||||
|
if err := g.renderLeftSkill(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Stats Button
|
||||||
|
w, _ = g.leftSkillResource.SkillIcon.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderNewStatsButton(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stamina
|
||||||
|
w, _ = g.mainPanel.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderStamina(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stamina status bar
|
||||||
|
w, _ = g.mainPanel.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderStaminaBar(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Experience status bar
|
||||||
|
if err := g.renderExperienceBar(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mini Panel and button
|
||||||
|
if err := g.renderMiniPanel(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potions
|
||||||
|
if err := g.renderPotions(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Skills Button
|
||||||
|
w, _ = g.mainPanel.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderNewSkillsButton(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right skill
|
||||||
|
w, _ = g.mainPanel.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderRightSkill(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mana Globe
|
||||||
|
w, _ = g.rightSkillResource.SkillIcon.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
|
if err := g.renderManaGlobe(offsetX, offsetY, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderPanel(x, y int, target d2interface.Surface) error {
|
||||||
if err := g.mainPanel.SetCurrentFrame(0); err != nil {
|
if err := g.mainPanel.SetCurrentFrame(0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, _ := g.mainPanel.GetCurrentFrameSize()
|
g.mainPanel.SetPosition(x, y)
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Health status bar
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderHealthGlobe(x, y int, target d2interface.Surface) error {
|
||||||
healthPercent := float64(g.hero.Stats.Health) / float64(g.hero.Stats.MaxHealth)
|
healthPercent := float64(g.hero.Stats.Health) / float64(g.hero.Stats.MaxHealth)
|
||||||
hpBarHeight := int(healthPercent * float64(globeHeight))
|
hpBarHeight := int(healthPercent * float64(globeHeight))
|
||||||
|
|
||||||
|
@ -1003,7 +1120,7 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
g.hpManaStatusSprite.SetPosition(offsetX+healthStatusOffsetX, height+healthStatusOffsetY)
|
g.hpManaStatusSprite.SetPosition(x+healthStatusOffsetX, y+healthStatusOffsetY)
|
||||||
|
|
||||||
healthMaskRect := image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight)
|
healthMaskRect := image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight)
|
||||||
if err := g.hpManaStatusSprite.RenderSection(target, healthMaskRect); err != nil {
|
if err := g.hpManaStatusSprite.RenderSection(target, healthMaskRect); err != nil {
|
||||||
|
@ -1015,15 +1132,16 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
g.globeSprite.SetPosition(offsetX+globeSpriteOffsetX, height+globeSpriteOffsetY)
|
g.globeSprite.SetPosition(x+globeSpriteOffsetX, y+globeSpriteOffsetY)
|
||||||
|
|
||||||
if err := g.globeSprite.Render(target); err != nil {
|
if err := g.globeSprite.Render(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetX += w
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Left skill
|
func (g *GameControls) renderLeftSkill(x, y int, target d2interface.Surface) error {
|
||||||
newSkillResourcePath := g.getSkillResourceByClass(g.hero.LeftSkill.Charclass)
|
newSkillResourcePath := g.getSkillResourceByClass(g.hero.LeftSkill.Charclass)
|
||||||
if newSkillResourcePath != g.leftSkillResource.SkillResourcePath {
|
if newSkillResourcePath != g.leftSkillResource.SkillResourcePath {
|
||||||
g.leftSkillResource.SkillResourcePath = newSkillResourcePath
|
g.leftSkillResource.SkillResourcePath = newSkillResourcePath
|
||||||
|
@ -1034,49 +1152,49 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, _ = g.leftSkillResource.SkillIcon.GetCurrentFrameSize()
|
g.leftSkillResource.SkillIcon.SetPosition(x, y)
|
||||||
|
|
||||||
g.leftSkillResource.SkillIcon.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.leftSkillResource.SkillIcon.Render(target); err != nil {
|
if err := g.leftSkillResource.SkillIcon.Render(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetX += w
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// New Stats Selector
|
func (g *GameControls) renderNewStatsButton(x, y int, target d2interface.Surface) error {
|
||||||
if err := g.mainPanel.SetCurrentFrame(frameNewStatsSelector); err != nil {
|
if err := g.mainPanel.SetCurrentFrame(frameNewStatsSelector); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, _ = g.mainPanel.GetCurrentFrameSize()
|
g.mainPanel.SetPosition(x, y)
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetX += w
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Stamina
|
func (g *GameControls) renderStamina(x, y int, target d2interface.Surface) error {
|
||||||
if err := g.mainPanel.SetCurrentFrame(frameStamina); err != nil {
|
if err := g.mainPanel.SetCurrentFrame(frameStamina); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, _ = g.mainPanel.GetCurrentFrameSize()
|
g.mainPanel.SetPosition(x, y)
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetX += w
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Stamina status bar
|
func (g *GameControls) renderStaminaBar(target d2interface.Surface) error {
|
||||||
target.PushTranslation(staminaBarOffsetX, staminaBarOffsetY)
|
target.PushTranslation(staminaBarOffsetX, staminaBarOffsetY)
|
||||||
|
defer target.Pop()
|
||||||
|
|
||||||
target.PushEffect(d2enum.DrawEffectModulate)
|
target.PushEffect(d2enum.DrawEffectModulate)
|
||||||
|
defer target.Pop()
|
||||||
|
|
||||||
staminaPercent := g.hero.Stats.Stamina / float64(g.hero.Stats.MaxStamina)
|
staminaPercent := g.hero.Stats.Stamina / float64(g.hero.Stats.MaxStamina)
|
||||||
|
|
||||||
|
@ -1086,18 +1204,25 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
target.DrawRect(int(staminaPercent*staminaBarWidth), staminaBarHeight, staminaBarColor)
|
target.DrawRect(int(staminaPercent*staminaBarWidth), staminaBarHeight, staminaBarColor)
|
||||||
target.Pop()
|
|
||||||
target.Pop()
|
|
||||||
|
|
||||||
// Experience status bar
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderExperienceBar(target d2interface.Surface) error {
|
||||||
target.PushTranslation(experienceBarOffsetX, experienceBarOffsetY)
|
target.PushTranslation(experienceBarOffsetX, experienceBarOffsetY)
|
||||||
|
defer target.Pop()
|
||||||
|
|
||||||
expPercent := float64(g.hero.Stats.Experience) / float64(g.hero.Stats.NextLevelExp)
|
expPercent := float64(g.hero.Stats.Experience) / float64(g.hero.Stats.NextLevelExp)
|
||||||
|
|
||||||
target.DrawRect(int(expPercent*expBarWidth), 2, d2util.Color(whiteAlpha100))
|
target.DrawRect(int(expPercent*expBarWidth), 2, d2util.Color(whiteAlpha100))
|
||||||
target.Pop()
|
|
||||||
|
|
||||||
// Center menu button
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderMiniPanel(target d2interface.Surface) error {
|
||||||
|
width, height := target.GetSize()
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
menuButtonFrameIndex := 0
|
menuButtonFrameIndex := 0
|
||||||
if g.miniPanel.isOpen {
|
if g.miniPanel.isOpen {
|
||||||
menuButtonFrameIndex = 2
|
menuButtonFrameIndex = 2
|
||||||
|
@ -1119,135 +1244,6 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Potions
|
|
||||||
if err := g.mainPanel.SetCurrentFrame(framePotions); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, _ = g.mainPanel.GetCurrentFrameSize()
|
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetX += w
|
|
||||||
|
|
||||||
// New Skills Selector
|
|
||||||
if err := g.mainPanel.SetCurrentFrame(frameNewSkillsSelector); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, _ = g.mainPanel.GetCurrentFrameSize()
|
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetX += w
|
|
||||||
|
|
||||||
// Right skill
|
|
||||||
newSkillResourcePath = g.getSkillResourceByClass(g.hero.RightSkill.Charclass)
|
|
||||||
if newSkillResourcePath != g.rightSkillResource.SkillResourcePath {
|
|
||||||
g.rightSkillResource.SkillIcon, _ = g.ui.NewSprite(newSkillResourcePath, d2resource.PaletteSky)
|
|
||||||
g.rightSkillResource.SkillResourcePath = newSkillResourcePath
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.rightSkillResource.SkillIcon.SetCurrentFrame(g.hero.RightSkill.IconCel); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, _ = g.rightSkillResource.SkillIcon.GetCurrentFrameSize()
|
|
||||||
|
|
||||||
g.rightSkillResource.SkillIcon.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.rightSkillResource.SkillIcon.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetX += w
|
|
||||||
|
|
||||||
// Right globe holder
|
|
||||||
if err := g.mainPanel.SetCurrentFrame(frameRightGlobeHolder); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
g.mainPanel.GetCurrentFrameSize()
|
|
||||||
|
|
||||||
g.mainPanel.SetPosition(offsetX, height)
|
|
||||||
|
|
||||||
if err := g.mainPanel.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mana status bar
|
|
||||||
manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana)
|
|
||||||
manaBarHeight := int(manaPercent * float64(globeHeight))
|
|
||||||
|
|
||||||
if err := g.hpManaStatusSprite.SetCurrentFrame(frameManaStatus); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
g.hpManaStatusSprite.SetPosition(offsetX+manaStatusOffsetX, height+manaStatusOffsetY)
|
|
||||||
|
|
||||||
manaMaskRect := image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight)
|
|
||||||
if err := g.hpManaStatusSprite.RenderSection(target, manaMaskRect); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Right globe
|
|
||||||
if err := g.globeSprite.SetCurrentFrame(frameRightGlobe); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
g.globeSprite.SetPosition(offsetX+rightGlobeOffsetX, height+rightGlobeOffsetY)
|
|
||||||
|
|
||||||
if err := g.globeSprite.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.globeSprite.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.isZoneTextShown {
|
|
||||||
g.zoneChangeText.SetPosition(zoneChangeTextX, zoneChangeTextY)
|
|
||||||
g.zoneChangeText.Render(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and format Health string from string lookup table.
|
|
||||||
fmtHealth := d2tbl.TranslateString("panelhealth")
|
|
||||||
healthCurr, healthMax := g.hero.Stats.Health, g.hero.Stats.MaxHealth
|
|
||||||
strPanelHealth := fmt.Sprintf(fmtHealth, healthCurr, healthMax)
|
|
||||||
|
|
||||||
// Display current hp and mana stats hpGlobe or manaGlobe region is clicked
|
|
||||||
if g.actionableRegions[hpGlobe].rect.IsInRect(mx, my) || g.hpStatsIsVisible {
|
|
||||||
g.hpManaStatsLabel.SetText(strPanelHealth)
|
|
||||||
g.hpManaStatsLabel.SetPosition(hpLabelX, hpLabelY)
|
|
||||||
g.hpManaStatsLabel.Render(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and format Mana string from string lookup table.
|
|
||||||
fmtMana := d2tbl.TranslateString("panelmana")
|
|
||||||
manaCurr, manaMax := g.hero.Stats.Mana, g.hero.Stats.MaxMana
|
|
||||||
strPanelMana := fmt.Sprintf(fmtMana, manaCurr, manaMax)
|
|
||||||
|
|
||||||
if g.actionableRegions[manaGlobe].rect.IsInRect(mx, my) || g.manaStatsIsVisible {
|
|
||||||
g.hpManaStatsLabel.SetText(strPanelMana)
|
|
||||||
// In case if the mana value gets higher, we need to shift the label to the left a little, hence widthManaLabel.
|
|
||||||
widthManaLabel, _ := g.hpManaStatsLabel.GetSize()
|
|
||||||
xManaLabel := manaLabelX - widthManaLabel
|
|
||||||
g.hpManaStatsLabel.SetPosition(xManaLabel, manaLabelY)
|
|
||||||
g.hpManaStatsLabel.Render(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.HelpOverlay.Render(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
miniPanelButtons := map[actionableType]string{
|
miniPanelButtons := map[actionableType]string{
|
||||||
miniPanelCharacter: "minipanelchar",
|
miniPanelCharacter: "minipanelchar",
|
||||||
miniPanelInventory: "minipanelinv",
|
miniPanelInventory: "minipanelinv",
|
||||||
|
@ -1258,46 +1254,18 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
miniPanelGameMenu: "minipanelmenubtn",
|
miniPanelGameMenu: "minipanelmenubtn",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !g.miniPanel.IsOpen() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
for miniPanelButton, stringTableKey := range miniPanelButtons {
|
for miniPanelButton, stringTableKey := range miniPanelButtons {
|
||||||
if !g.miniPanel.IsOpen() {
|
if !g.actionableRegions[miniPanelButton].rect.IsInRect(mx, my) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.actionableRegions[miniPanelButton].rect.IsInRect(mx, my) {
|
rect := &g.actionableRegions[miniPanelButton].rect
|
||||||
rect := &g.actionableRegions[miniPanelButton].rect
|
|
||||||
g.nameLabel.SetText(d2tbl.TranslateString(stringTableKey))
|
|
||||||
|
|
||||||
halfButtonWidth := rect.Width >> 1
|
|
||||||
halfButtonHeight := rect.Height >> 1
|
|
||||||
|
|
||||||
centerX := rect.Left + halfButtonWidth
|
|
||||||
centerY := rect.Top + halfButtonHeight
|
|
||||||
|
|
||||||
_, labelHeight := g.nameLabel.GetSize()
|
|
||||||
|
|
||||||
labelX := centerX
|
|
||||||
labelY := centerY - halfButtonHeight - labelHeight
|
|
||||||
|
|
||||||
g.nameLabel.SetPosition(labelX, labelY)
|
|
||||||
g.nameLabel.Render(target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display run/walk tooltip when hovered.
|
|
||||||
// Note that whether the player is walking or running, the tooltip is the same in Diablo 2.
|
|
||||||
if g.actionableRegions[walkRun].rect.IsInRect(mx, my) {
|
|
||||||
var stringTableKey string
|
|
||||||
|
|
||||||
if g.hero.IsRunToggled() {
|
|
||||||
stringTableKey = "RunOff"
|
|
||||||
} else {
|
|
||||||
stringTableKey = "RunOn"
|
|
||||||
}
|
|
||||||
|
|
||||||
g.nameLabel.SetText(d2tbl.TranslateString(stringTableKey))
|
g.nameLabel.SetText(d2tbl.TranslateString(stringTableKey))
|
||||||
|
|
||||||
rect := &g.actionableRegions[walkRun].rect
|
|
||||||
|
|
||||||
halfButtonWidth := rect.Width >> 1
|
halfButtonWidth := rect.Width >> 1
|
||||||
halfButtonHeight := rect.Height >> 1
|
halfButtonHeight := rect.Height >> 1
|
||||||
|
|
||||||
|
@ -1313,71 +1281,250 @@ func (g *GameControls) renderHUD(target d2interface.Surface) error {
|
||||||
g.nameLabel.Render(target)
|
g.nameLabel.Render(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
return nil
|
||||||
staminaExperienceY = 535
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Display stamina tooltip when hovered.
|
func (g *GameControls) renderPotions(x, _ int, target d2interface.Surface) error {
|
||||||
if g.actionableRegions[stamina].rect.IsInRect(mx, my) {
|
_, height := target.GetSize()
|
||||||
// Create and format Stamina string from string lookup table.
|
|
||||||
fmtStamina := d2tbl.TranslateString("panelstamina")
|
|
||||||
staminaCurr, staminaMax := int(g.hero.Stats.Stamina), g.hero.Stats.MaxStamina
|
|
||||||
strPanelStamina := fmt.Sprintf(fmtStamina, staminaCurr, staminaMax)
|
|
||||||
|
|
||||||
g.nameLabel.SetText(strPanelStamina)
|
if err := g.mainPanel.SetCurrentFrame(framePotions); err != nil {
|
||||||
|
return err
|
||||||
rect := &g.actionableRegions[stamina].rect
|
|
||||||
|
|
||||||
halfButtonWidth := rect.Width >> 1
|
|
||||||
centerX := rect.Left + halfButtonWidth
|
|
||||||
|
|
||||||
_, labelHeight := g.nameLabel.GetSize()
|
|
||||||
halfLabelHeight := labelHeight >> 1
|
|
||||||
|
|
||||||
labelX := centerX
|
|
||||||
labelY := staminaExperienceY - halfLabelHeight
|
|
||||||
|
|
||||||
g.nameLabel.SetPosition(labelX, labelY)
|
|
||||||
g.nameLabel.Render(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display experience tooltip when hovered.
|
g.mainPanel.SetPosition(x, height)
|
||||||
if g.actionableRegions[xp].rect.IsInRect(mx, my) {
|
|
||||||
// Create and format Experience string from string lookup table.
|
|
||||||
fmtExp := d2tbl.TranslateString("panelexp")
|
|
||||||
|
|
||||||
// The English string for "panelexp" is "Experience: %u / %u", however %u doesn't
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
// translate well. So we need to rewrite %u into a formatable Go verb. %d is used in other
|
return err
|
||||||
// strings, so we go with that, keeping in mind that %u likely referred to
|
|
||||||
// an unsigned integer.
|
|
||||||
fmtExp = strings.ReplaceAll(fmtExp, "%u", "%d")
|
|
||||||
|
|
||||||
expCurr, expMax := uint(g.hero.Stats.Experience), uint(g.hero.Stats.NextLevelExp)
|
|
||||||
strPanelExp := fmt.Sprintf(fmtExp, expCurr, expMax)
|
|
||||||
|
|
||||||
g.nameLabel.SetText(strPanelExp)
|
|
||||||
rect := &g.actionableRegions[stamina].rect
|
|
||||||
|
|
||||||
halfButtonWidth := rect.Width >> 1
|
|
||||||
centerX := rect.Left + halfButtonWidth
|
|
||||||
|
|
||||||
_, labelHeight := g.nameLabel.GetSize()
|
|
||||||
halfLabelHeight := labelHeight >> 1
|
|
||||||
|
|
||||||
labelX := centerX
|
|
||||||
labelY := staminaExperienceY - halfLabelHeight
|
|
||||||
|
|
||||||
g.nameLabel.SetPosition(labelX, labelY)
|
|
||||||
g.nameLabel.Render(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.skillSelectMenu.IsOpen() {
|
|
||||||
g.skillSelectMenu.Render(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderNewSkillsButton(x, _ int, target d2interface.Surface) error {
|
||||||
|
_, height := target.GetSize()
|
||||||
|
|
||||||
|
if err := g.mainPanel.SetCurrentFrame(frameNewSkillsSelector); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.mainPanel.SetPosition(x, height)
|
||||||
|
|
||||||
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderRightSkill(x, _ int, target d2interface.Surface) error {
|
||||||
|
_, height := target.GetSize()
|
||||||
|
|
||||||
|
newSkillResourcePath := g.getSkillResourceByClass(g.hero.RightSkill.Charclass)
|
||||||
|
if newSkillResourcePath != g.rightSkillResource.SkillResourcePath {
|
||||||
|
g.rightSkillResource.SkillIcon, _ = g.ui.NewSprite(newSkillResourcePath, d2resource.PaletteSky)
|
||||||
|
g.rightSkillResource.SkillResourcePath = newSkillResourcePath
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.rightSkillResource.SkillIcon.SetCurrentFrame(g.hero.RightSkill.IconCel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.rightSkillResource.SkillIcon.SetPosition(x, height)
|
||||||
|
|
||||||
|
if err := g.rightSkillResource.SkillIcon.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderManaGlobe(x, _ int, target d2interface.Surface) error {
|
||||||
|
_, height := target.GetSize()
|
||||||
|
|
||||||
|
if err := g.mainPanel.SetCurrentFrame(frameRightGlobeHolder); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.mainPanel.SetPosition(x, height)
|
||||||
|
|
||||||
|
if err := g.mainPanel.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mana status bar
|
||||||
|
manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana)
|
||||||
|
manaBarHeight := int(manaPercent * float64(globeHeight))
|
||||||
|
|
||||||
|
if err := g.hpManaStatusSprite.SetCurrentFrame(frameManaStatus); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.hpManaStatusSprite.SetPosition(x+manaStatusOffsetX, height+manaStatusOffsetY)
|
||||||
|
|
||||||
|
manaMaskRect := image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight)
|
||||||
|
if err := g.hpManaStatusSprite.RenderSection(target, manaMaskRect); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right globe
|
||||||
|
if err := g.globeSprite.SetCurrentFrame(frameRightGlobe); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.globeSprite.SetPosition(x+rightGlobeOffsetX, height+rightGlobeOffsetY)
|
||||||
|
|
||||||
|
if err := g.globeSprite.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.globeSprite.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderHealthTooltip(target d2interface.Surface) {
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
|
// Create and format Health string from string lookup table.
|
||||||
|
fmtHealth := d2tbl.TranslateString("panelhealth")
|
||||||
|
healthCurr, healthMax := g.hero.Stats.Health, g.hero.Stats.MaxHealth
|
||||||
|
strPanelHealth := fmt.Sprintf(fmtHealth, healthCurr, healthMax)
|
||||||
|
|
||||||
|
// Display current hp and mana stats hpGlobe or manaGlobe region is clicked
|
||||||
|
if !g.actionableRegions[hpGlobe].rect.IsInRect(mx, my) || g.hpStatsIsVisible {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g.hpManaStatsLabel.SetText(strPanelHealth)
|
||||||
|
g.hpManaStatsLabel.SetPosition(hpLabelX, hpLabelY)
|
||||||
|
g.hpManaStatsLabel.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderManaTooltip(target d2interface.Surface) {
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
|
// Create and format Mana string from string lookup table.
|
||||||
|
fmtMana := d2tbl.TranslateString("panelmana")
|
||||||
|
manaCurr, manaMax := g.hero.Stats.Mana, g.hero.Stats.MaxMana
|
||||||
|
strPanelMana := fmt.Sprintf(fmtMana, manaCurr, manaMax)
|
||||||
|
|
||||||
|
if !g.actionableRegions[manaGlobe].rect.IsInRect(mx, my) || g.manaStatsIsVisible {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g.hpManaStatsLabel.SetText(strPanelMana)
|
||||||
|
// In case if the mana value gets higher, we need to shift the
|
||||||
|
// label to the left a little, hence widthManaLabel.
|
||||||
|
widthManaLabel, _ := g.hpManaStatsLabel.GetSize()
|
||||||
|
xManaLabel := manaLabelX - widthManaLabel
|
||||||
|
g.hpManaStatsLabel.SetPosition(xManaLabel, manaLabelY)
|
||||||
|
g.hpManaStatsLabel.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderRunWalkTooltip(target d2interface.Surface) {
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
|
// Display run/walk tooltip when hovered.
|
||||||
|
// Note that whether the player is walking or running, the tooltip is the same in Diablo 2.
|
||||||
|
if !g.actionableRegions[walkRun].rect.IsInRect(mx, my) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var stringTableKey string
|
||||||
|
|
||||||
|
if g.hero.IsRunToggled() {
|
||||||
|
stringTableKey = "RunOff"
|
||||||
|
} else {
|
||||||
|
stringTableKey = "RunOn"
|
||||||
|
}
|
||||||
|
|
||||||
|
g.nameLabel.SetText(d2tbl.TranslateString(stringTableKey))
|
||||||
|
|
||||||
|
rect := &g.actionableRegions[walkRun].rect
|
||||||
|
|
||||||
|
halfButtonWidth := rect.Width >> 1
|
||||||
|
halfButtonHeight := rect.Height >> 1
|
||||||
|
|
||||||
|
centerX := rect.Left + halfButtonWidth
|
||||||
|
centerY := rect.Top + halfButtonHeight
|
||||||
|
|
||||||
|
_, labelHeight := g.nameLabel.GetSize()
|
||||||
|
|
||||||
|
labelX := centerX
|
||||||
|
labelY := centerY - halfButtonHeight - labelHeight
|
||||||
|
|
||||||
|
g.nameLabel.SetPosition(labelX, labelY)
|
||||||
|
g.nameLabel.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderStaminaTooltip(target d2interface.Surface) {
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
|
// Display stamina tooltip when hovered.
|
||||||
|
if !g.actionableRegions[stamina].rect.IsInRect(mx, my) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and format Stamina string from string lookup table.
|
||||||
|
fmtStamina := d2tbl.TranslateString("panelstamina")
|
||||||
|
staminaCurr, staminaMax := int(g.hero.Stats.Stamina), g.hero.Stats.MaxStamina
|
||||||
|
strPanelStamina := fmt.Sprintf(fmtStamina, staminaCurr, staminaMax)
|
||||||
|
|
||||||
|
g.nameLabel.SetText(strPanelStamina)
|
||||||
|
|
||||||
|
rect := &g.actionableRegions[stamina].rect
|
||||||
|
|
||||||
|
halfButtonWidth := rect.Width >> 1
|
||||||
|
centerX := rect.Left + halfButtonWidth
|
||||||
|
|
||||||
|
_, labelHeight := g.nameLabel.GetSize()
|
||||||
|
halfLabelHeight := labelHeight >> 1
|
||||||
|
|
||||||
|
labelX := centerX
|
||||||
|
labelY := staminaExperienceY - halfLabelHeight
|
||||||
|
|
||||||
|
g.nameLabel.SetPosition(labelX, labelY)
|
||||||
|
g.nameLabel.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) renderExperienceTooltip(target d2interface.Surface) {
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
|
||||||
|
// Display experience tooltip when hovered.
|
||||||
|
if !g.actionableRegions[xp].rect.IsInRect(mx, my) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and format Experience string from string lookup table.
|
||||||
|
fmtExp := d2tbl.TranslateString("panelexp")
|
||||||
|
|
||||||
|
// The English string for "panelexp" is "Experience: %u / %u", however %u doesn't
|
||||||
|
// translate well. So we need to rewrite %u into a formatable Go verb. %d is used in other
|
||||||
|
// strings, so we go with that, keeping in mind that %u likely referred to
|
||||||
|
// an unsigned integer.
|
||||||
|
fmtExp = strings.ReplaceAll(fmtExp, "%u", "%d")
|
||||||
|
|
||||||
|
expCurr, expMax := uint(g.hero.Stats.Experience), uint(g.hero.Stats.NextLevelExp)
|
||||||
|
strPanelExp := fmt.Sprintf(fmtExp, expCurr, expMax)
|
||||||
|
|
||||||
|
g.nameLabel.SetText(strPanelExp)
|
||||||
|
rect := &g.actionableRegions[stamina].rect
|
||||||
|
|
||||||
|
halfButtonWidth := rect.Width >> 1
|
||||||
|
centerX := rect.Left + halfButtonWidth
|
||||||
|
|
||||||
|
_, labelHeight := g.nameLabel.GetSize()
|
||||||
|
halfLabelHeight := labelHeight >> 1
|
||||||
|
|
||||||
|
labelX := centerX
|
||||||
|
labelY := staminaExperienceY - halfLabelHeight
|
||||||
|
|
||||||
|
g.nameLabel.SetPosition(labelX, labelY)
|
||||||
|
g.nameLabel.Render(target)
|
||||||
|
}
|
||||||
|
|
||||||
// SetZoneChangeText sets the zoneChangeText
|
// SetZoneChangeText sets the zoneChangeText
|
||||||
func (g *GameControls) SetZoneChangeText(text string) {
|
func (g *GameControls) SetZoneChangeText(text string) {
|
||||||
g.zoneChangeText.SetText(text)
|
g.zoneChangeText.SetText(text)
|
||||||
|
|
|
@ -15,6 +15,25 @@ import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
the 800x600 help screen dc6 file frames look like this
|
||||||
|
the position we set for frames is the lower-left corner x,y
|
||||||
|
+----+------------------+-------------------+------------+----+
|
||||||
|
| 1 | 3 | 4 | 5 | 6 |
|
||||||
|
| |------------------+-------------------| | |
|
||||||
|
| | | | |
|
||||||
|
| | | | |
|
||||||
|
+----+ +------------+----+
|
||||||
|
| 2 | | 7 |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
+----+ +----+
|
||||||
|
*/
|
||||||
|
const (
|
||||||
|
// if you add up frame widths 1,3,4,5,6 you get (65+255+255+245+20) = 840
|
||||||
|
magicHelpBorderOffsetX = -40
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
frameTopLeft = iota
|
frameTopLeft = iota
|
||||||
frameBottomLeft
|
frameBottomLeft
|
||||||
|
@ -217,25 +236,13 @@ func (h *Overlay) IsInRect(px, py int) bool {
|
||||||
|
|
||||||
// Load the overlay graphical assets
|
// Load the overlay graphical assets
|
||||||
func (h *Overlay) Load() {
|
func (h *Overlay) Load() {
|
||||||
/*
|
h.setupOverlayFrame()
|
||||||
the 800x600 help screen dc6 file frames look like this
|
h.setupTitleAndButton()
|
||||||
the position we set for frames is the lower-left corner x,y
|
h.setupBulletedList()
|
||||||
+----+------------------+-------------------+------------+----+
|
h.setupLabelsWithLines()
|
||||||
| 1 | 3 | 4 | 5 | 6 |
|
}
|
||||||
| |------------------+-------------------| | |
|
|
||||||
| | | | |
|
|
||||||
| | | | |
|
|
||||||
+----+ +------------+----+
|
|
||||||
| 2 | | 7 |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
+----+ +----+
|
|
||||||
*/
|
|
||||||
const (
|
|
||||||
// if you add up frame widths 1,3,4,5,6 you get (65+255+255+245+20) = 840
|
|
||||||
magicHelpBorderOffsetX = -40
|
|
||||||
)
|
|
||||||
|
|
||||||
|
func (h *Overlay) setupOverlayFrame() {
|
||||||
frames := []int{
|
frames := []int{
|
||||||
frameTopLeft,
|
frameTopLeft,
|
||||||
frameBottomLeft,
|
frameBottomLeft,
|
||||||
|
@ -295,9 +302,10 @@ func (h *Overlay) Load() {
|
||||||
|
|
||||||
h.frames = append(h.frames, f)
|
h.frames = append(h.frames, f)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Overlay) setupTitleAndButton() {
|
||||||
// Title
|
// Title
|
||||||
|
|
||||||
text := d2tbl.TranslateString("Strhelp1") // "Diablo II Help"
|
text := d2tbl.TranslateString("Strhelp1") // "Diablo II Help"
|
||||||
newLabel := h.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
newLabel := h.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||||
newLabel.SetText(text)
|
newLabel.SetText(text)
|
||||||
|
@ -307,8 +315,7 @@ func (h *Overlay) Load() {
|
||||||
newLabel.SetPosition((windowWidth/inHalf)-(titleLabelWidth/inHalf)+titleLabelOffsetX, 0)
|
newLabel.SetPosition((windowWidth/inHalf)-(titleLabelWidth/inHalf)+titleLabelOffsetX, 0)
|
||||||
h.text = append(h.text, newLabel)
|
h.text = append(h.text, newLabel)
|
||||||
|
|
||||||
// Close
|
// Button
|
||||||
|
|
||||||
h.closeButton = h.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
h.closeButton = h.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
||||||
h.closeButton.SetPosition(closeButtonX, closeButtonY)
|
h.closeButton.SetPosition(closeButtonX, closeButtonY)
|
||||||
h.closeButton.SetVisible(false)
|
h.closeButton.SetVisible(false)
|
||||||
|
@ -318,7 +325,9 @@ func (h *Overlay) Load() {
|
||||||
newLabel.SetText(d2tbl.TranslateString("strClose")) // "Close"
|
newLabel.SetText(d2tbl.TranslateString("strClose")) // "Close"
|
||||||
newLabel.SetPosition(closeButtonLabelX, closeButtonLabelY)
|
newLabel.SetPosition(closeButtonLabelX, closeButtonLabelY)
|
||||||
h.text = append(h.text, newLabel)
|
h.text = append(h.text, newLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Overlay) setupBulletedList() {
|
||||||
// Bullets
|
// Bullets
|
||||||
// the hotkeys displayed here should be pulled from a mapping of input events to game events
|
// the hotkeys displayed here should be pulled from a mapping of input events to game events
|
||||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/793
|
// https://github.com/OpenDiablo2/OpenDiablo2/issues/793
|
||||||
|
@ -360,9 +369,10 @@ func (h *Overlay) Load() {
|
||||||
DotY: listBulletRootY + listItemOffsetY,
|
DotY: listBulletRootY + listItemOffsetY,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Callouts
|
// nolint:funlen // can't reduce
|
||||||
|
func (h *Overlay) setupLabelsWithLines() {
|
||||||
h.createCallout(callout{
|
h.createCallout(callout{
|
||||||
LabelText: d2tbl.TranslateString("strlvlup"), // "New Stats"
|
LabelText: d2tbl.TranslateString("strlvlup"), // "New Stats"
|
||||||
LabelX: newStatsLabelX,
|
LabelX: newStatsLabelX,
|
||||||
|
|
|
@ -201,8 +201,8 @@ func makeCloseButtonPos(close1, close2, close3 int) [numTabs]int {
|
||||||
return [numTabs]int{close1, close2, close3}
|
return [numTabs]int{close1, close2, close3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *skillTree) getTab(class d2enum.Hero) (heroTabData, bool) {
|
func (s *skillTree) getTab(class d2enum.Hero) *heroTabData {
|
||||||
tabMap := map[d2enum.Hero]heroTabData{
|
tabMap := map[d2enum.Hero]*heroTabData{
|
||||||
d2enum.HeroBarbarian: {
|
d2enum.HeroBarbarian: {
|
||||||
&skillTreeHeroTypeResources{
|
&skillTreeHeroTypeResources{
|
||||||
skillPanelPath: d2resource.SkillsPanelBarbarian,
|
skillPanelPath: d2resource.SkillsPanelBarbarian,
|
||||||
|
@ -242,13 +242,11 @@ func (s *skillTree) getTab(class d2enum.Hero) (heroTabData, bool) {
|
||||||
skillCloseButtonXMiddle,
|
skillCloseButtonXMiddle,
|
||||||
skillCloseButtonXLeft),
|
skillCloseButtonXLeft),
|
||||||
},
|
},
|
||||||
|
|
||||||
d2enum.HeroAssassin: {
|
d2enum.HeroAssassin: {
|
||||||
&skillTreeHeroTypeResources{
|
&skillTreeHeroTypeResources{
|
||||||
skillPanelPath: d2resource.SkillsPanelAssassin,
|
skillPanelPath: d2resource.SkillsPanelAssassin,
|
||||||
skillIconPath: d2resource.AssassinSkills,
|
skillIconPath: d2resource.AssassinSkills,
|
||||||
},
|
},
|
||||||
|
|
||||||
makeTabString("StrSklTree30"),
|
makeTabString("StrSklTree30"),
|
||||||
makeTabString("StrSklTree31", "StrSklTree32"),
|
makeTabString("StrSklTree31", "StrSklTree32"),
|
||||||
makeTabString("StrSklTree33", "StrSklTree34"),
|
makeTabString("StrSklTree33", "StrSklTree34"),
|
||||||
|
@ -270,7 +268,6 @@ func (s *skillTree) getTab(class d2enum.Hero) (heroTabData, bool) {
|
||||||
skillCloseButtonXLeft,
|
skillCloseButtonXLeft,
|
||||||
skillCloseButtonXRight),
|
skillCloseButtonXRight),
|
||||||
},
|
},
|
||||||
|
|
||||||
d2enum.HeroAmazon: {
|
d2enum.HeroAmazon: {
|
||||||
&skillTreeHeroTypeResources{
|
&skillTreeHeroTypeResources{
|
||||||
skillPanelPath: d2resource.SkillsPanelAmazon,
|
skillPanelPath: d2resource.SkillsPanelAmazon,
|
||||||
|
@ -284,7 +281,6 @@ func (s *skillTree) getTab(class d2enum.Hero) (heroTabData, bool) {
|
||||||
skillCloseButtonXMiddle,
|
skillCloseButtonXMiddle,
|
||||||
skillCloseButtonXLeft),
|
skillCloseButtonXLeft),
|
||||||
},
|
},
|
||||||
|
|
||||||
d2enum.HeroDruid: {
|
d2enum.HeroDruid: {
|
||||||
&skillTreeHeroTypeResources{
|
&skillTreeHeroTypeResources{
|
||||||
skillPanelPath: d2resource.SkillsPanelDruid,
|
skillPanelPath: d2resource.SkillsPanelDruid,
|
||||||
|
@ -300,14 +296,12 @@ func (s *skillTree) getTab(class d2enum.Hero) (heroTabData, bool) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
entry, found := tabMap[class]
|
return tabMap[class]
|
||||||
|
|
||||||
return entry, found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *skillTree) setHeroTypeResourcePath() {
|
func (s *skillTree) setHeroTypeResourcePath() {
|
||||||
entry, found := s.getTab(s.heroClass)
|
entry := s.getTab(s.heroClass)
|
||||||
if !found {
|
if entry == nil {
|
||||||
log.Fatal("Unknown Hero Type")
|
log.Fatal("Unknown Hero Type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user