Quest log initial (#956)

* Adding character quest panel
This commit is contained in:
gucio321 2020-12-02 08:19:15 +01:00 committed by GitHub
parent b936608651
commit 96916863ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 700 additions and 41 deletions

View File

@ -110,7 +110,7 @@ const (
HealthManaIndicator = "/data/global/ui/PANEL/hlthmana.DC6"
AddSkillButton = "/data/global/ui/PANEL/level.DC6"
GoldMoveDialog = "/data/global/ui/menu/dialogbackground.DC6"
WPTabs = "/data/global/ui/menu/expwaygatetabs.dc6"
WPTabs = "/data/global/ui/MENU/expwaygatetabs.dc6"
WPBg = "/data/global/ui/menu/waygatebackground.dc6"
WPIcons = "/data/global/ui/menu/waygateicons.dc6"
@ -186,34 +186,35 @@ const (
SkillIcon = "/data/global/ui/PANEL/Skillicon.DC6"
// --- Quest Log---
QuestLogBg = "/data/global/ui/menu/questbackground.dc6"
QuestLogDone = "/data/global/ui/menu/questdone.dc6"
QuestLogQDescr = "/data/global/ui/menu/questlast.dc6"
QuestLogSocket = "/data/global/ui/menu/questsocket.dc6"
QuestLogA1Q1 = "/data/global/ui/menu/a1q1.dc6"
QuestLogA1Q2 = "/data/global/ui/menu/a1q2.dc6"
QuestLogA1Q3 = "/data/global/ui/menu/a1q3.dc6"
QuestLogA1Q4 = "/data/global/ui/menu/a1q4.dc6"
QuestLogA1Q5 = "/data/global/ui/menu/a1q5.dc6"
QuestLogA1Q6 = "/data/global/ui/menu/a1q6.dc6"
QuestLogA2Q1 = "/data/global/ui/menu/a2q1.dc6"
QuestLogA2Q2 = "/data/global/ui/menu/a2q2.dc6"
QuestLogA2Q3 = "/data/global/ui/menu/a2q3.dc6"
QuestLogA2Q4 = "/data/global/ui/menu/a2q4.dc6"
QuestLogA2Q5 = "/data/global/ui/menu/a2q5.dc6"
QuestLogA2Q6 = "/data/global/ui/menu/a2q6.dc6"
QuestLogA3Q1 = "/data/global/ui/menu/a3q1.dc6"
QuestLogA3Q2 = "/data/global/ui/menu/a3q2.dc6"
QuestLogA3Q3 = "/data/global/ui/menu/a3q3.dc6"
QuestLogA3Q4 = "/data/global/ui/menu/a3q4.dc6"
QuestLogA3Q5 = "/data/global/ui/menu/a3q5.dc6"
QuestLogA3Q6 = "/data/global/ui/menu/a3q6.dc6"
QuestLogA4Q1 = "/data/global/ui/menu/a4q1.dc6"
QuestLogA4Q2 = "/data/global/ui/menu/a4q2.dc6"
QuestLogA4Q3 = "/data/global/ui/menu/a4q3.dc6"
QuestLogA4Q4 = "/data/global/ui/menu/a4q4.dc6"
QuestLogA4Q5 = "/data/global/ui/menu/a4q5.dc6"
QuestLogA4Q6 = "/data/global/ui/menu/a4q6.dc6"
QuestLogBg = "/data/global/ui/MENU/questbackground.dc6"
QuestLogDone = "/data/global/ui/MENU/questdone.dc6"
QuestLogTabs = "/data/global/ui/MENU/expquesttabs.dc6"
QuestLogQDescrBtn = "/data/global/ui/MENU/questlast.dc6"
QuestLogSocket = "/data/global/ui/MENU/questsockets.dc6"
QuestLogA1Q1 = "/data/global/ui/MENU/a1q1.dc6"
QuestLogA1Q2 = "/data/global/ui/MENU/a1q2.dc6"
QuestLogA1Q3 = "/data/global/ui/MENU/a1q3.dc6"
QuestLogA1Q4 = "/data/global/ui/MENU/a1q4.dc6"
QuestLogA1Q5 = "/data/global/ui/MENU/a1q5.dc6"
QuestLogA1Q6 = "/data/global/ui/MENU/a1q6.dc6"
QuestLogA2Q1 = "/data/global/ui/MENU/a2q1.dc6"
QuestLogA2Q2 = "/data/global/ui/MENU/a2q2.dc6"
QuestLogA2Q3 = "/data/global/ui/MENU/a2q3.dc6"
QuestLogA2Q4 = "/data/global/ui/MENU/a2q4.dc6"
QuestLogA2Q5 = "/data/global/ui/MENU/a2q5.dc6"
QuestLogA2Q6 = "/data/global/ui/MENU/a2q6.dc6"
QuestLogA3Q1 = "/data/global/ui/MENU/a3q1.dc6"
QuestLogA3Q2 = "/data/global/ui/MENU/a3q2.dc6"
QuestLogA3Q3 = "/data/global/ui/MENU/a3q3.dc6"
QuestLogA3Q4 = "/data/global/ui/MENU/a3q4.dc6"
QuestLogA3Q5 = "/data/global/ui/MENU/a3q5.dc6"
QuestLogA3Q6 = "/data/global/ui/MENU/a3q6.dc6"
QuestLogA4Q1 = "/data/global/ui/MENU/a4q1.dc6"
QuestLogA4Q2 = "/data/global/ui/MENU/a4q2.dc6"
QuestLogA4Q3 = "/data/global/ui/MENU/a4q3.dc6"
QuestLogA4Q4 = "/data/global/ui/MENU/a4q4.dc6"
QuestLogA4Q5 = "/data/global/ui/MENU/a4q5.dc6"
QuestLogA4Q6 = "/data/global/ui/MENU/a4q6.dc6"
// --- Mouse Pointers ---

View File

@ -40,16 +40,24 @@ const (
ButtonTypeSquareClose ButtonType = 20
ButtonTypeSquareOk ButtonType = 21
ButtonTypeSkillTreeTab ButtonType = 22
ButtonTypeMinipanelOpenClose ButtonType = 23
ButtonTypeMinipanelParty ButtonType = 24
ButtonTypeBuy ButtonType = 25
ButtonTypeSell ButtonType = 26
ButtonTypeRepair ButtonType = 27
ButtonTypeRepairAll ButtonType = 28
ButtonTypeLeftArrow ButtonType = 29
ButtonTypeRightArrow ButtonType = 30
ButtonTypeQuery ButtonType = 31
ButtonTypeSquelchChat ButtonType = 32
ButtonTypeQuestDescr ButtonType = 23 // I suppose it should be also used in WP tabs
ButtonTypeMinipanelOpenClose ButtonType = 24
ButtonTypeMinipanelParty ButtonType = 25
ButtonTypeBuy ButtonType = 26
ButtonTypeSell ButtonType = 27
ButtonTypeRepair ButtonType = 28
ButtonTypeRepairAll ButtonType = 29
ButtonTypeLeftArrow ButtonType = 30
ButtonTypeRightArrow ButtonType = 31
ButtonTypeQuery ButtonType = 32
ButtonTypeSquelchChat ButtonType = 33
ButtonTypeTab1 ButtonType = 34
ButtonTypeTab2 ButtonType = 35
ButtonTypeTab3 ButtonType = 36
ButtonTypeTab4 ButtonType = 37
ButtonTypeTab5 ButtonType = 38
ButtonTypeTabBlank ButtonType = 39
ButtonTypeBlankQuestBtn ButtonType = 40
ButtonNoFixedWidth int = -1
ButtonNoFixedHeight int = -1
@ -74,6 +82,14 @@ const (
squelchChatButtonBaseFrame = 20 // base frame offset of the "?" button dc6
)
const (
tab1BaseFrame = 0
tab2BaseFrame = 2
tab3BaseFrame = 4
tab4BaseFrame = 6
tab5BaseFrame = 8
)
const (
greyAlpha100 = 0x646464ff
lightGreyAlpha75 = 0x808080c3
@ -160,10 +176,17 @@ const (
buttonSkillTreeTabFixedWidth = 93
buttonSkillTreeTabFixedHeight = 107
buttonTabXSegments = 1
buttonTabYSegments = 1
buttonMinipanelOpenCloseBaseFrame = 0
buttonMinipanelXSegments = 1
buttonMinipanelYSegments = 1
blankQuestButtonXSegments = 1
blankQuestButtonYSegments = 1
blankQuestButtonDisabledFrames = -1
buttonMinipanelCharacterBaseFrame = 0
buttonMinipanelInventoryBaseFrame = 2
buttonMinipanelSkilltreeBaseFrame = 4
@ -493,6 +516,131 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
TooltipXOffset: buttonBuySellTooltipXOffset,
TooltipYOffset: buttonBuySellTooltipYOffset,
},
ButtonTypeQuestDescr: {
XSegments: buttonBuySellSegmentsX,
YSegments: buttonBuySellSegmentsY,
DisabledFrame: buttonBuySellDisabledFrame,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.QuestLogQDescrBtn,
PaletteName: d2resource.PaletteUnits,
Toggleable: true,
FontPath: d2resource.Font30,
AllowFrameChange: true,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTab1: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: tab1BaseFrame + 1,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: false,
FontPath: d2resource.Font30,
AllowFrameChange: true,
BaseFrame: tab1BaseFrame,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTab2: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: tab2BaseFrame + 1,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: false,
FontPath: d2resource.Font30,
AllowFrameChange: true,
BaseFrame: tab2BaseFrame,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTab3: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: tab3BaseFrame + 1,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: false,
FontPath: d2resource.Font30,
AllowFrameChange: true,
BaseFrame: tab3BaseFrame,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTab4: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: tab4BaseFrame + 1,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: false,
FontPath: d2resource.Font30,
AllowFrameChange: true,
BaseFrame: tab4BaseFrame,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTab5: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: tab5BaseFrame + 1,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: false,
FontPath: d2resource.Font30,
AllowFrameChange: true,
BaseFrame: tab5BaseFrame,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeTabBlank: {
XSegments: buttonTabXSegments,
YSegments: buttonTabYSegments,
DisabledFrame: 0,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.WPTabs,
PaletteName: d2resource.PaletteUnits,
Toggleable: true,
FontPath: d2resource.Font30,
AllowFrameChange: false,
HasImage: false,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeBlankQuestBtn: {
XSegments: blankQuestButtonXSegments,
YSegments: blankQuestButtonYSegments,
DisabledFrame: blankQuestButtonDisabledFrames,
DisabledColor: lightGreyAlpha75,
ResourceName: d2resource.QuestLogDone,
PaletteName: d2resource.PaletteUnits,
Toggleable: true,
FontPath: d2resource.Font30,
AllowFrameChange: false,
HasImage: false,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
LabelColor: greyAlpha100,
},
ButtonTypeSkillTreeTab: {
XSegments: buttonSkillTreeTabXSegments,
YSegments: buttonSkillTreeTabYSegments,

View File

@ -9,8 +9,10 @@ type RenderPriority int
const (
RenderPriorityBackground RenderPriority = iota
RenderPrioritySkilltree
RenderPriorityInventory
RenderPrioritySkilltreeIcon
RenderPriorityHeroStatsPanel
RenderPriorityQuestLog
RenderPriorityHUDPanel
RenderPriorityMinipanel
RenderPriorityHelpPanel

View File

@ -209,6 +209,7 @@ func NewGameControls(
inventoryRecord := asset.Records.Layout.Inventory[inventoryRecordKey]
heroStatsPanel := NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, l, hero.Stats)
questLog := NewQuestLog(asset, ui, l, 1) // need to be changed
inventory := NewInventory(asset, ui, l, hero.Gold, inventoryRecord)
skilltree := newSkillTree(hero.Skills, hero.Class, asset, l, ui)
@ -239,6 +240,7 @@ func NewGameControls(
inventory: inventory,
skilltree: skilltree,
heroStatsPanel: heroStatsPanel,
questLog: questLog,
HelpOverlay: helpOverlay,
keyMap: keyMap,
hud: hud,
@ -267,6 +269,7 @@ func NewGameControls(
}
gc.heroStatsPanel.SetOnCloseCb(gc.onCloseHeroStatsPanel)
gc.questLog.SetOnCloseCb(gc.onCloseQuestLog)
gc.inventory.SetOnCloseCb(gc.onCloseInventory)
gc.skilltree.SetOnCloseCb(gc.onCloseSkilltree)
@ -301,6 +304,7 @@ type GameControls struct {
hud *HUD
skilltree *skillTree
heroStatsPanel *HeroStatsPanel
questLog *QuestLog
HelpOverlay *HelpOverlay
bottomMenuRect *d2geom.Rectangle
leftMenuRect *d2geom.Rectangle
@ -385,6 +389,7 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
g.inventory.Close()
g.skilltree.Close()
g.heroStatsPanel.Close()
g.questLog.Close()
g.HelpOverlay.Close()
g.updateLayout()
case d2enum.ToggleInventoryPanel:
@ -393,6 +398,8 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
g.toggleInventoryPanel()
case d2enum.ToggleCharacterPanel:
g.toggleHeroStatsPanel()
case d2enum.ToggleQuestLog:
g.toggleQuestLog()
case d2enum.ToggleRunWalk:
g.hud.onToggleRunButton(false)
case d2enum.HoldRun:
@ -454,6 +461,12 @@ func (g *GameControls) onEscKey() {
escHandled = true
}
if g.questLog.IsOpen() {
g.questLog.Close()
escHandled = true
}
if g.HelpOverlay.IsOpen() {
g.HelpOverlay.Toggle()
@ -611,6 +624,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
}
func (g *GameControls) toggleHeroStatsPanel() {
g.questLog.Close()
g.heroStatsPanel.Toggle()
g.hud.miniPanel.SetMovedRight(g.heroStatsPanel.IsOpen())
g.updateLayout()
@ -621,6 +635,18 @@ func (g *GameControls) onCloseHeroStatsPanel() {
g.updateLayout()
}
func (g *GameControls) toggleQuestLog() {
g.heroStatsPanel.Close()
g.questLog.Toggle()
g.hud.miniPanel.SetMovedRight(g.questLog.IsOpen())
g.updateLayout()
}
func (g *GameControls) onCloseQuestLog() {
g.hud.miniPanel.SetMovedRight(g.questLog.IsOpen())
g.updateLayout()
}
func (g *GameControls) toggleInventoryPanel() {
g.skilltree.Close()
g.inventory.Toggle()
@ -649,6 +675,7 @@ func (g *GameControls) openEscMenu() {
g.inventory.Close()
g.skilltree.Close()
g.heroStatsPanel.Close()
g.questLog.Close()
g.hud.miniPanel.closeDisabled()
g.escapeMenu.open()
g.updateLayout()
@ -660,6 +687,7 @@ func (g *GameControls) Load() {
g.inventory.Load()
g.skilltree.load()
g.heroStatsPanel.Load()
g.questLog.Load()
g.HelpOverlay.Load()
miniPanelActions := &miniPanelActions{
@ -667,6 +695,7 @@ func (g *GameControls) Load() {
inventoryToggle: g.toggleInventoryPanel,
skilltreeToggle: g.toggleSkilltreePanel,
menuToggle: g.openEscMenu,
questToggle: g.toggleQuestLog,
}
g.hud.miniPanel.load(miniPanelActions)
}
@ -699,7 +728,7 @@ func (g *GameControls) updateLayout() {
func (g *GameControls) isLeftPanelOpen() bool {
// https://github.com/OpenDiablo2/OpenDiablo2/issues/801
return g.heroStatsPanel.IsOpen()
return g.heroStatsPanel.IsOpen() || g.questLog.IsOpen()
}
func (g *GameControls) isRightPanelOpen() bool {

View File

@ -204,6 +204,7 @@ func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) {
s.renderStaticLabels(target)
}
// nolint:dupl // see quest_log.go.renderStaticPanelFrames comment
func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) {
frames := []int{
statsPanelTopLeft,

View File

@ -98,7 +98,7 @@ func (g *Inventory) Toggle() {
func (g *Inventory) Load() {
var err error
g.panelGroup = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
g.panelGroup = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityInventory)
g.panelMoveGold = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
g.frame = d2ui.NewUIFrame(g.asset, g.uiManager, d2ui.FrameRight)

View File

@ -0,0 +1,478 @@
package d2player
import (
"fmt"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
const white = 0xffffffff
const (
act1 = iota + 1
act2
act3
act4
act5
)
const ( // for the dc6 frames
questLogTopLeft = iota
questLogTopRight
questLogBottomLeft
questLogBottomRight
)
const (
normalActQuestsNumber = 6
act4QuestsNumber = 3
)
const (
questLogOffsetX, questLogOffsetY = 80, 64
)
const (
iconOffsetY = 88
questOffsetX, questOffsetY = 4, 4
q1SocketX, q1SocketY = 100, 95
q2SocketX, q2SocketY = 200, 95
q3SocketX, q3SocketY = 300, 95
q4SocketX, q4SocketY = 100, 190
q5SocketX, q5SocketY = 200, 190
q6SocketX, q6SocketY = 300, 190
)
const (
questLogCloseButtonX, questLogCloseButtonY = 358, 455
questLogDescrButtonX, questLogDescrButtonY = 308, 457
questLabelX, questLabelY = 240, 297
)
// toset
const (
questTabY = 66
questTab1X = 85
questTab2X = 143
questTab3X = 201
questTab4X = 259
questTab5X = 317
)
const (
questLogTab1 = iota
questLogTab2
questLogTab3
questLogTab4
questLogTab5
questLogNumTabs
)
const (
questNone = 0
)
// NewQuestLog creates a new quest log
func NewQuestLog(asset *d2asset.AssetManager,
ui *d2ui.UIManager,
act int,
l d2util.LogLevel) *QuestLog {
originX := 0
originY := 0
ql := &QuestLog{
asset: asset,
uiManager: ui,
originX: originX,
originY: originY,
act: act,
tab: [questLogNumTabs]*questLogTab{
{},
{},
{},
{},
{},
},
selectedQuest: 1,
}
ql.Logger = d2util.NewLogger()
ql.Logger.SetLevel(l)
ql.Logger.SetPrefix(logPrefix)
return ql
}
// QuestLog represents the quest log
type QuestLog struct {
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
panel *d2ui.Sprite
onCloseCb func()
panelGroup *d2ui.WidgetGroup
selectedTab int
selectedQuest int
act int
tab [questLogNumTabs]*questLogTab
questName *d2ui.Label
questsa1 *d2ui.WidgetGroup
questsa2 *d2ui.WidgetGroup
questsa3 *d2ui.WidgetGroup
questsa4 *d2ui.WidgetGroup
questsa5 *d2ui.WidgetGroup
originX int
originY int
isOpen bool
*d2util.Logger
}
type questLogTab struct {
button *d2ui.Button
invisibleButton *d2ui.Button
}
func (q *questLogTab) newTab(ui *d2ui.UIManager, tabType d2ui.ButtonType, x int) {
q.button = ui.NewButton(tabType, "")
q.invisibleButton = ui.NewButton(d2ui.ButtonTypeTabBlank, "")
q.button.SetPosition(x, questTabY)
q.invisibleButton.SetPosition(x, questTabY)
}
// Load the data for the hero status panel
func (s *QuestLog) Load() {
var err error
s.questsa1 = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
s.questsa2 = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
s.questsa3 = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
s.questsa4 = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
s.questsa5 = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
s.panelGroup.AddWidget(frame)
s.panel, err = s.uiManager.NewSprite(d2resource.QuestLogBg, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
w, h := frame.GetSize()
staticPanel := s.uiManager.NewCustomWidgetCached(s.renderStaticMenu, w, h)
s.panelGroup.AddWidget(staticPanel)
closeButton := s.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
closeButton.SetVisible(false)
closeButton.SetPosition(questLogCloseButtonX, questLogCloseButtonY)
closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(closeButton)
descrButton := s.uiManager.NewButton(d2ui.ButtonTypeQuestDescr, "")
descrButton.SetVisible(false)
descrButton.SetPosition(questLogDescrButtonX, questLogDescrButtonY)
descrButton.OnActivated(s.onDescrClicked)
s.panelGroup.AddWidget(descrButton)
s.questName = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteStatic)
s.questName.Alignment = d2ui.HorizontalAlignCenter
s.questName.Color[0] = rgbaColor(white)
s.questName.SetPosition(questLabelX, questLabelY)
s.panelGroup.AddWidget(s.questName)
s.loadTabs()
s.loadQuestIcons()
s.panelGroup.SetVisible(false)
}
func (s *QuestLog) questTable(act, number int) struct {
name string
numberOfDescrs int
status int
frame int
x int
y int
} {
var quests = []struct {
name string // name of quest in string table
numberOfDescrs int // number of possible descriptions (not used yet)
status int // status of quest (not used yet)
frame int // frame of quest
x, y int // position of quest
}{
{"qstsa1q1", 5, 0, 0, q1SocketX, q1SocketY},
{"qstsa1q2", 0, 0, 1, q2SocketX, q2SocketY},
{"qstsa1q3", 0, 0, 2, q3SocketX, q3SocketY},
{"qstsa1q4", 0, 0, 3, q4SocketX, q4SocketY},
{"qstsa1q5", 0, 0, 4, q5SocketX, q5SocketY},
{"qstsa1q6", 0, 0, 5, q6SocketX, q6SocketY},
{"qstsa2q1", 0, 0, 6, q1SocketX, q1SocketY},
{"qstsa2q2", 0, 0, 7, q2SocketX, q2SocketY},
{"qstsa2q3", 0, 0, 8, q3SocketX, q3SocketY},
{"qstsa2q4", 0, 0, 9, q4SocketX, q4SocketY},
{"qstsa2q5", 0, 0, 10, q5SocketX, q5SocketY},
{"qstsa2q6", 0, 0, 11, q6SocketX, q6SocketY},
{"qstsa3q1", 0, 0, 12, q1SocketX, q1SocketY},
{"qstsa3q2", 0, 0, 13, q2SocketX, q2SocketY},
{"qstsa3q3", 0, 0, 14, q3SocketX, q3SocketY},
{"qstsa3q4", 0, 0, 15, q4SocketX, q4SocketY},
{"qstsa3q5", 0, 0, 16, q5SocketX, q5SocketY},
{"qstsa3q6", 0, 0, 17, q6SocketX, q6SocketY},
{"qstsa4q1", 0, 0, 18, q1SocketX, q1SocketY},
{"qstsa4q2", 0, 0, 19, q2SocketX, q2SocketY},
{"qstsa4q3", 0, 0, 20, q3SocketX, q3SocketY},
{"qstsa5q1", 0, 0, 21, q1SocketX, q1SocketY},
{"qstsa5q2", 0, 0, 22, q2SocketX, q2SocketY},
{"qstsa5q3", 0, 0, 23, q3SocketX, q3SocketY},
{"qstsa5q4", 0, 0, 24, q4SocketX, q4SocketY},
{"qstsa5q5", 0, 0, 25, q5SocketX, q5SocketY},
{"qstsa5q6", 0, 0, 26, q6SocketX, q6SocketY},
}
key := (act-1)*normalActQuestsNumber + number
if act > act4 {
key -= act4QuestsNumber
}
return quests[key]
}
func (s *QuestLog) loadQuestIcons() {
s.questsa1 = s.loadQuestIconsForAct(act1)
s.questsa2 = s.loadQuestIconsForAct(act2)
s.questsa3 = s.loadQuestIconsForAct(act3)
s.questsa4 = s.loadQuestIconsForAct(act4)
s.questsa5 = s.loadQuestIconsForAct(act5)
}
func (s *QuestLog) makeQuestCallback(n int) func() {
return func() {
s.onQuestClicked(n + 1)
}
}
func (s *QuestLog) loadQuestIconsForAct(act int) *d2ui.WidgetGroup {
wg := s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog)
var questsInAct int
if act == act4 {
questsInAct = act4QuestsNumber
} else {
questsInAct = normalActQuestsNumber
}
for n := 0; n < questsInAct; n++ {
q := s.questTable(act, n)
button := s.uiManager.NewButton(d2ui.ButtonTypeBlankQuestBtn, "")
button.SetPosition(q.x+questOffsetX, q.y+questOffsetY)
button.OnActivated(s.makeQuestCallback(n))
socket, err := s.uiManager.NewSprite(d2resource.QuestLogSocket, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
socket.SetPosition(q.x+questOffsetX, q.y+iconOffsetY+2*questOffsetY)
icon, err := s.uiManager.NewSprite(d2resource.QuestLogDone, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
err = icon.SetCurrentFrame(q.frame)
if err != nil {
s.Error(err.Error())
}
icon.SetPosition(q.x+questOffsetX, q.y+questOffsetY+iconOffsetY)
wg.AddWidget(icon)
wg.AddWidget(socket)
wg.AddWidget(button)
}
wg.SetVisible(false)
return wg
}
func (s *QuestLog) loadQuestLabels() {
if s.selectedQuest == 0 {
s.questName.SetText("")
return
}
s.questName.SetText(s.asset.TranslateString(fmt.Sprintf("qstsa%dq%d", s.selectedTab+1, s.selectedQuest)))
}
func (s *QuestLog) loadTabs() {
s.tab[questLogTab1].newTab(s.uiManager, d2ui.ButtonTypeTab1, questTab1X)
s.tab[questLogTab1].invisibleButton.OnActivated(func() { s.setTab(questLogTab1) })
s.panelGroup.AddWidget(s.tab[questLogTab1].button)
s.panelGroup.AddWidget(s.tab[questLogTab1].invisibleButton)
s.tab[questLogTab2].newTab(s.uiManager, d2ui.ButtonTypeTab2, questTab2X)
s.tab[questLogTab2].invisibleButton.OnActivated(func() { s.setTab(questLogTab2) })
s.panelGroup.AddWidget(s.tab[questLogTab2].button)
s.panelGroup.AddWidget(s.tab[questLogTab2].invisibleButton)
s.tab[questLogTab3].newTab(s.uiManager, d2ui.ButtonTypeTab3, questTab3X)
s.tab[questLogTab3].invisibleButton.OnActivated(func() { s.setTab(questLogTab3) })
s.panelGroup.AddWidget(s.tab[questLogTab3].button)
s.panelGroup.AddWidget(s.tab[questLogTab3].invisibleButton)
s.tab[questLogTab4].newTab(s.uiManager, d2ui.ButtonTypeTab4, questTab4X)
s.tab[questLogTab4].invisibleButton.OnActivated(func() { s.setTab(questLogTab4) })
s.panelGroup.AddWidget(s.tab[questLogTab4].button)
s.panelGroup.AddWidget(s.tab[questLogTab4].invisibleButton)
s.tab[questLogTab5].newTab(s.uiManager, d2ui.ButtonTypeTab5, questTab5X)
s.tab[questLogTab5].invisibleButton.OnActivated(func() { s.setTab(questLogTab5) })
s.panelGroup.AddWidget(s.tab[questLogTab5].button)
s.panelGroup.AddWidget(s.tab[questLogTab5].invisibleButton)
s.setTab(s.act - 1)
}
func (s *QuestLog) setTab(tab int) {
s.selectedTab = tab
s.selectedQuest = questNone
s.loadQuestLabels()
s.questsa1.SetVisible(tab == questLogTab1)
s.questsa2.SetVisible(tab == questLogTab2)
s.questsa3.SetVisible(tab == questLogTab3)
s.questsa4.SetVisible(tab == questLogTab4)
s.questsa5.SetVisible(tab == questLogTab5)
for i := 0; i < questLogNumTabs; i++ {
s.tab[i].button.SetEnabled(i == tab)
}
}
func (s *QuestLog) onQuestClicked(number int) {
s.selectedQuest = number
s.loadQuestLabels()
s.Infof("Quest number %d in tab %d clicked", number, s.selectedTab)
}
func (s *QuestLog) onDescrClicked() {
//
}
// IsOpen returns true if the hero status panel is open
func (s *QuestLog) IsOpen() bool {
return s.isOpen
}
// Toggle toggles the visibility of the hero status panel
func (s *QuestLog) Toggle() {
if s.isOpen {
s.Close()
} else {
s.Open()
}
}
// Open opens the hero status panel
func (s *QuestLog) Open() {
s.isOpen = true
s.panelGroup.SetVisible(true)
s.setTab(s.selectedTab)
}
// Close closed the hero status panel
func (s *QuestLog) Close() {
s.isOpen = false
s.panelGroup.SetVisible(false)
s.questsa1.SetVisible(false)
s.questsa2.SetVisible(false)
s.questsa3.SetVisible(false)
s.questsa4.SetVisible(false)
s.questsa5.SetVisible(false)
s.onCloseCb()
}
// SetOnCloseCb the callback run on closing the HeroStatsPanel
func (s *QuestLog) SetOnCloseCb(cb func()) {
s.onCloseCb = cb
}
// Advance updates labels on the panel
func (s *QuestLog) Advance(elapsed float64) {
//
}
func (s *QuestLog) renderStaticMenu(target d2interface.Surface) {
s.renderStaticPanelFrames(target)
}
// nolint:dupl // I think it is OK, to duplicate this function
func (s *QuestLog) renderStaticPanelFrames(target d2interface.Surface) {
frames := []int{
questLogTopLeft,
questLogTopRight,
questLogBottomRight,
questLogBottomLeft,
}
currentX := s.originX + questLogOffsetX
currentY := s.originY + questLogOffsetY
for _, frameIndex := range frames {
if err := s.panel.SetCurrentFrame(frameIndex); err != nil {
s.Error(err.Error())
}
w, h := s.panel.GetCurrentFrameSize()
switch frameIndex {
case questLogTopLeft:
s.panel.SetPosition(currentX, currentY+h)
currentX += w
case questLogTopRight:
s.panel.SetPosition(currentX, currentY+h)
currentY += h
case questLogBottomRight:
s.panel.SetPosition(currentX, currentY+h)
case questLogBottomLeft:
s.panel.SetPosition(currentX-w, currentY+h)
}
s.panel.Render(target)
}
}
// copy from character select
func rgbaColor(rgba uint32) color.RGBA {
result := color.RGBA{}
a, b, g, r := 0, 1, 2, 3
byteWidth := 8
byteMask := 0xff
for idx := 0; idx < 4; idx++ {
shift := idx * byteWidth
component := uint8(rgba>>shift) & uint8(byteMask)
switch idx {
case a:
result.A = component
case b:
result.B = component
case g:
result.G = component
case r:
result.R = component
}
}
return result
}