diff --git a/d2common/d2resource/resource_paths.go b/d2common/d2resource/resource_paths.go index a18a196f..ed74d366 100644 --- a/d2common/d2resource/resource_paths.go +++ b/d2common/d2resource/resource_paths.go @@ -193,6 +193,7 @@ const ( QuestLogQDescrBtn = "/data/global/ui/MENU/questlast.dc6" QuestLogSocket = "/data/global/ui/MENU/questsockets.dc6" QuestLogAQuestAnimation = "/data/global/ui/MENU/a%dq%d.dc6" + QuestLogDoneSfx = "cursor/questdone.wav" // --- Mouse Pointers --- diff --git a/d2game/d2gamescreen/game.go b/d2game/d2gamescreen/game.go index 07a826c1..2b339a01 100644 --- a/d2game/d2gamescreen/game.go +++ b/d2game/d2gamescreen/game.go @@ -304,7 +304,8 @@ func (v *Game) bindGameControls() error { var err error v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player, v.gameClient.MapEngine, - v.escapeMenu, v.mapRenderer, v, v.terminal, v.uiManager, v.keyMap, v.logLevel, v.gameClient.IsSinglePlayer()) + v.escapeMenu, v.mapRenderer, v, v.terminal, v.uiManager, v.keyMap, v.audioProvider, v.logLevel, + v.gameClient.IsSinglePlayer()) if err != nil { return err diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index 2335cc52..f1fc3b5e 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -124,6 +124,7 @@ func NewGameControls( term d2interface.Terminal, ui *d2ui.UIManager, keyMap *KeyMap, + audioProvider d2interface.AudioProvider, l d2util.LogLevel, isSinglePlayer bool, ) (*GameControls, error) { @@ -207,7 +208,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, hero.Act) + questLog := NewQuestLog(asset, ui, l, audioProvider, hero.Act) inventory, err := NewInventory(asset, ui, l, hero.Gold, inventoryRecord) if err != nil { @@ -728,6 +729,7 @@ func (g *GameControls) Advance(elapsed float64) error { g.mapRenderer.Advance(elapsed) g.hud.Advance(elapsed) g.inventory.Advance(elapsed) + g.questLog.Advance(elapsed) if err := g.escapeMenu.Advance(elapsed); err != nil { return err diff --git a/d2game/d2player/quest_log.go b/d2game/d2player/quest_log.go index e064eb11..1d0eace8 100644 --- a/d2game/d2player/quest_log.go +++ b/d2game/d2player/quest_log.go @@ -71,6 +71,7 @@ func (s *QuestLog) getPositionForSocket(number int) (x, y int) { func NewQuestLog(asset *d2asset.AssetManager, ui *d2ui.UIManager, l d2util.LogLevel, + audioProvider d2interface.AudioProvider, act int) *QuestLog { originX := 0 originY := 0 @@ -106,9 +107,9 @@ func NewQuestLog(asset *d2asset.AssetManager, 26: 0, } - var quests [d2enum.ActsNumber]*d2ui.WidgetGroup + var quests [d2enum.ActsNumber]*questEntire for i := 0; i < d2enum.ActsNumber; i++ { - quests[i] = ui.NewWidgetGroup(d2ui.RenderPriorityQuestLog) + quests[i] = &questEntire{WidgetGroup: ui.NewWidgetGroup(d2ui.RenderPriorityQuestLog)} } var tabs [d2enum.ActsNumber]questLogTab @@ -129,6 +130,7 @@ func NewQuestLog(asset *d2asset.AssetManager, quests: quests, questStatus: qs, maxPlayersAct: mpa, + audioProvider: audioProvider, } ql.Logger = d2util.NewLogger() @@ -149,10 +151,12 @@ type QuestLog struct { selectedQuest int act int tab [d2enum.ActsNumber]questLogTab + audioProvider d2interface.AudioProvider + completeSound d2interface.SoundEffect questName *d2ui.Label questDescr *d2ui.Label - quests [d2enum.ActsNumber]*d2ui.WidgetGroup + quests [d2enum.ActsNumber]*questEntire questStatus map[int]int maxPlayersAct int @@ -163,6 +167,11 @@ type QuestLog struct { *d2util.Logger } +type questEntire struct { + *d2ui.WidgetGroup + icons []*d2ui.Sprite +} + /* questIconTab returns path to quest animation using its act and number. From d2resource: QuestLogAQuestAnimation = "/data/global/ui/MENU/a%dq%d.dc6"*/ @@ -187,6 +196,8 @@ type questLogTab struct { func (s *QuestLog) Load() { var err error + s.completeSound, err = s.audioProvider.LoadSound(d2resource.QuestLogDoneSfx, false, false) + s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog) frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft) @@ -228,7 +239,8 @@ func (s *QuestLog) Load() { s.loadTabs() for i := 0; i < d2enum.ActsNumber; i++ { - s.quests[i] = s.loadQuestIconsForAct(i + 1) + item, icons := s.loadQuestIconsForAct(i + 1) + s.quests[i] = &questEntire{item, icons} } s.panelGroup.SetVisible(false) @@ -268,7 +280,7 @@ func (s *QuestLog) loadTabs() { s.setTab(s.act - 1) } -func (s *QuestLog) loadQuestIconsForAct(act int) *d2ui.WidgetGroup { +func (s *QuestLog) loadQuestIconsForAct(act int) (*d2ui.WidgetGroup, []*d2ui.Sprite) { wg := s.uiManager.NewWidgetGroup(d2ui.RenderPriorityQuestLog) var questsInAct int @@ -282,6 +294,8 @@ func (s *QuestLog) loadQuestIconsForAct(act int) *d2ui.WidgetGroup { var buttons []*d2ui.Button + var icons []*d2ui.Sprite + var icon *d2ui.Sprite for n := 0; n < questsInAct; n++ { @@ -307,7 +321,8 @@ func (s *QuestLog) loadQuestIconsForAct(act int) *d2ui.WidgetGroup { } icon.SetPosition(x+questOffsetX, y+questOffsetY+iconOffsetY) - wg.AddWidget(icon) + + icons = append(icons, icon) } for i := 0; i < questsInAct; i++ { @@ -338,9 +353,13 @@ func (s *QuestLog) loadQuestIconsForAct(act int) *d2ui.WidgetGroup { wg.AddWidget(b) } + for _, i := range icons { + wg.AddWidget(i) + } + wg.SetVisible(false) - return wg + return wg, icons } func (s *QuestLog) makeQuestIconForAct(act, n int) (*d2ui.Sprite, error) { @@ -355,16 +374,6 @@ func (s *QuestLog) makeQuestIconForAct(act, n int) (*d2ui.Sprite, error) { case d2enum.QuestStatusCompleted: err = icon.SetCurrentFrame(completedFrame) case d2enum.QuestStatusCompleting: - // that's not complet now - err = icon.SetCurrentFrame(0) - if err != nil { - s.Error(err.Error()) - } - - icon.PlayForward() - icon.SetPlayLoop(false) - err = icon.SetCurrentFrame(completedFrame) - s.questStatus[s.cordsToQuestID(act, n)] = d2enum.QuestStatusCompleted case d2enum.QuestStatusNotStarted: err = icon.SetCurrentFrame(notStartedFrame) default: @@ -374,6 +383,26 @@ func (s *QuestLog) makeQuestIconForAct(act, n int) (*d2ui.Sprite, error) { return icon, err } +func (s *QuestLog) playQuestAnimations() { + var err error + + for j, i := range s.quests[s.selectedTab].icons { + questID := s.cordsToQuestID(s.selectedTab+1, j) + if s.questStatus[questID] == d2enum.QuestStatusCompleting { + s.completeSound.Play() + err = i.SetCurrentFrame(0) + if err != nil { + s.Error(err.Error()) + } + + i.SetPlayLength(3) + i.PlayForward() + i.SetPlayLoop(false) + s.questStatus[questID] = d2enum.QuestStatusCompleted + } + } +} + func (s *QuestLog) setQuestLabel() { if s.selectedQuest == 0 { s.questName.SetText("") @@ -466,6 +495,7 @@ func (s *QuestLog) Open() { s.isOpen = true s.panelGroup.SetVisible(true) s.setTab(s.selectedTab) + s.playQuestAnimations() } // Close closed the hero status panel @@ -487,7 +517,15 @@ func (s *QuestLog) SetOnCloseCb(cb func()) { // Advance updates labels on the panel func (s *QuestLog) Advance(elapsed float64) { - // + if !s.IsOpen() { + return + } + + for _, i := range s.quests[s.selectedTab].icons { + if err := i.Advance(elapsed); err != nil { + s.Error(err.Error()) + } + } } func (s *QuestLog) renderStaticMenu(target d2interface.Surface) {