From 9a7f27ae8308410ab7b15e4dd5cda1c242bdd274 Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Mon, 18 Jan 2021 21:11:50 +0100 Subject: [PATCH] party panel: party panel & multiplayer init --- d2game/d2gamescreen/game.go | 7 +- d2game/d2player/game_controls.go | 17 ++--- d2game/d2player/party_panel.go | 115 +++++++++++++++++++++---------- 3 files changed, 92 insertions(+), 47 deletions(-) diff --git a/d2game/d2gamescreen/game.go b/d2game/d2gamescreen/game.go index 4247ff36..5ee10d83 100644 --- a/d2game/d2gamescreen/game.go +++ b/d2game/d2gamescreen/game.go @@ -223,6 +223,7 @@ func (v *Game) Render(screen d2interface.Surface) { } // Advance runs the update logic on the Gameplay screen +// nolint:gocyclo // not need to change func (v *Game) Advance(elapsed float64) error { v.soundEngine.Advance(elapsed) @@ -278,6 +279,10 @@ func (v *Game) Advance(elapsed float64) error { v.soundEnv.Advance(elapsed) + if v.gameControls != nil { + v.gameControls.PartyPanel.UpdatePlayersList(v.gameClient.Players) + } + return nil } @@ -292,7 +297,7 @@ 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.audioProvider, v.logLevel, - v.gameClient.IsSinglePlayer()) + v.gameClient.IsSinglePlayer(), v.gameClient.Players) if err != nil { return err diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index 3e96d280..12a0eda6 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -109,6 +109,7 @@ func NewGameControls( audioProvider d2interface.AudioProvider, l d2util.LogLevel, isSinglePlayer bool, + players map[string]*d2mapentity.Player, ) (*GameControls, error) { var inventoryRecordKey string @@ -173,7 +174,7 @@ func NewGameControls( heroStatsPanel := NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, l, hero.Stats) - partyPanel := NewPartyPanel(asset, ui, hero.Name(), l, hero, hero.Stats) + PartyPanel := NewPartyPanel(asset, ui, hero.Name(), l, hero, hero.Stats, players) questLog := NewQuestLog(asset, ui, l, audioProvider, hero.Act) @@ -207,7 +208,7 @@ func NewGameControls( inventory: inventory, skilltree: skilltree, heroStatsPanel: heroStatsPanel, - partyPanel: partyPanel, + PartyPanel: PartyPanel, questLog: questLog, HelpOverlay: helpOverlay, keyMap: keyMap, @@ -277,7 +278,7 @@ type GameControls struct { hud *HUD skilltree *skillTree heroStatsPanel *HeroStatsPanel - partyPanel *PartyPanel + PartyPanel *PartyPanel questLog *QuestLog HelpOverlay *HelpOverlay bottomMenuRect *d2geom.Rectangle @@ -560,7 +561,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool { func (g *GameControls) clearLeftScreenSide() { g.heroStatsPanel.Close() - g.partyPanel.Close() + g.PartyPanel.Close() g.questLog.Close() g.hud.skillSelectMenu.ClosePanels() g.hud.miniPanel.SetMovedRight(false) @@ -615,7 +616,7 @@ func (g *GameControls) toggleHeroStatsPanel() { } func (g *GameControls) togglePartyPanel() { - g.openLeftPanel(g.partyPanel) + g.openLeftPanel(g.PartyPanel) } func (g *GameControls) onCloseHeroStatsPanel() { @@ -679,7 +680,7 @@ func (g *GameControls) Load() { g.inventory.Load() g.skilltree.load() g.heroStatsPanel.Load() - g.partyPanel.Load() + g.PartyPanel.Load() g.questLog.Load() g.HelpOverlay.Load() @@ -703,7 +704,7 @@ func (g *GameControls) Advance(elapsed float64) error { g.hud.Advance(elapsed) g.inventory.Advance(elapsed) g.questLog.Advance(elapsed) - g.partyPanel.Advance(elapsed) + g.PartyPanel.Advance(elapsed) if err := g.escapeMenu.Advance(elapsed); err != nil { return err @@ -731,7 +732,7 @@ func (g *GameControls) updateLayout() { } func (g *GameControls) isLeftPanelOpen() bool { - return g.heroStatsPanel.IsOpen() || g.partyPanel.IsOpen() || g.questLog.IsOpen() || g.inventory.moveGoldPanel.IsOpen() + return g.heroStatsPanel.IsOpen() || g.PartyPanel.IsOpen() || g.questLog.IsOpen() || g.inventory.moveGoldPanel.IsOpen() } func (g *GameControls) isRightPanelOpen() bool { diff --git a/d2game/d2player/party_panel.go b/d2game/d2player/party_panel.go index b305e9ec..75085575 100644 --- a/d2game/d2player/party_panel.go +++ b/d2game/d2player/party_panel.go @@ -83,6 +83,16 @@ func (s *PartyPanel) newPartyIndex() *partyIndex { result.level = levelLabel relationships := s.createSwitcher(relationshipsFrame) + + result.relationshipsActiveTooltip = s.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteSky, d2ui.TooltipXCenter, d2ui.TooltipYTop) + result.relationshipsActiveTooltip.SetText(s.asset.TranslateString("strParty7") + "\n" + s.asset.TranslateString("strParty8")) + relationships.SetActiveTooltip(result.relationshipsActiveTooltip) + + result.relationshipsInactiveTooltip = s.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteSky, + d2ui.TooltipXCenter, d2ui.TooltipYTop) + result.relationshipsInactiveTooltip.SetText(s.asset.TranslateString("strParty9") + "\n" + s.asset.TranslateString("strParty8")) + relationships.SetInactiveTooltip(result.relationshipsInactiveTooltip) + result.relationshipSwitcher = relationships seeing := s.createSwitcher(seeingButtonFrame) @@ -114,18 +124,20 @@ func (s *PartyPanel) newPartyIndex() *partyIndex { // partyIndex represents a party index type partyIndex struct { - hero *d2mapentity.Player - name *d2ui.Label - class *d2ui.Label - level *d2ui.Label - relationshipSwitcher *d2ui.SwitchableButton - seeingSwitcher *d2ui.SwitchableButton - seeingActiveTooltip *d2ui.Tooltip - seeingInactiveTooltip *d2ui.Tooltip - listeningSwitcher *d2ui.SwitchableButton - listeningActiveTooltip *d2ui.Tooltip - listeningInactiveTooltip *d2ui.Tooltip - relationships d2enum.PlayersRelationships + hero *d2mapentity.Player + name *d2ui.Label + class *d2ui.Label + level *d2ui.Label + relationshipSwitcher *d2ui.SwitchableButton + relationshipsActiveTooltip *d2ui.Tooltip + relationshipsInactiveTooltip *d2ui.Tooltip + seeingSwitcher *d2ui.SwitchableButton + seeingActiveTooltip *d2ui.Tooltip + seeingInactiveTooltip *d2ui.Tooltip + listeningSwitcher *d2ui.SwitchableButton + listeningActiveTooltip *d2ui.Tooltip + listeningInactiveTooltip *d2ui.Tooltip + relationships d2enum.PlayersRelationships } // setColor sets appropriate labels' colors @@ -153,7 +165,12 @@ func (pi *partyIndex) setPositions(idx int) { pi.name.SetPosition(nameLabelX, baseNameLabelY+nextBar*idx) pi.class.SetPosition(classLabelX, baseClassLabelY+nextBar*idx) pi.level.SetPosition(levelLabelX, baseLevelLabelY+nextBar*idx) + pi.relationshipSwitcher.SetPosition(relationshipSwitcherX, baseRelationshipSwitcherY+nextBar*idx) + _, h = pi.relationshipsActiveTooltip.GetSize() + pi.relationshipsActiveTooltip.SetPosition(relationshipSwitcherX+buttonSize, baseRelationshipSwitcherY+idx*nextBar-h) + _, h = pi.relationshipsInactiveTooltip.GetSize() + pi.relationshipsInactiveTooltip.SetPosition(relationshipSwitcherX+buttonSize, baseRelationshipSwitcherY+idx*nextBar-h) pi.seeingSwitcher.SetPosition(seeingSwitcherX, baseSeeingSwitcherY+idx*nextBar) _, h = pi.seeingActiveTooltip.GetSize() @@ -263,6 +280,22 @@ func (s *PartyPanel) Sort() { } } +// IsInPanel returns true if player given already exists in panel +func (s *PartyPanel) IsInPanel(player *d2mapentity.Player) bool { + for _, i := range s.partyIndexes { + if i.hero == player { + return true + } + } + + return false +} + +// IsMe returns true if player given is "me" +func (s *PartyPanel) IsMe(player *d2mapentity.Player) bool { + return player == s.me +} + // setBarPosition sets party-panel bar's position func (s *PartyPanel) setBarPosition() { for n, i := range s.partyIndexes { @@ -275,16 +308,28 @@ func (s *PartyPanel) setBarPosition() { } } +// UpdatePanel updates panel indexes with players list +func (s *PartyPanel) UpdatePanel() { + for _, i := range s.players { + if !s.IsInPanel(i) && !s.IsMe(i) { + s.AddPlayer(i, d2enum.PlayerRelationNeutral) + + // we need to switch all hidden widgets to be visible + if s.IsOpen() { + s.Open() + } + } + } +} + // NewPartyPanel creates a new party panel func NewPartyPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName string, l d2util.LogLevel, - - // example Player structure (me) - testPlayer *d2mapentity.Player, - - heroState *d2hero.HeroStatsState) *PartyPanel { + me *d2mapentity.Player, + heroState *d2hero.HeroStatsState, + players map[string]*d2mapentity.Player) *PartyPanel { log.Print("OpenDiablo2 - Party Panel - development") originX := 0 @@ -300,8 +345,8 @@ func NewPartyPanel(asset *d2asset.AssetManager, labels: &StatsPanelLabels{}, barX: barX, barY: baseBarY, - - testPlayer: testPlayer, + players: players, + me: me, } var partyIndexes [maxPlayersInGame]*partyIndex @@ -337,6 +382,9 @@ type PartyPanel struct { partyIndexes [maxPlayersInGame]*partyIndex indexes [maxPlayersInGame]*d2ui.WidgetGroup + players map[string]*d2mapentity.Player + me *d2mapentity.Player + originX int originY int isOpen bool @@ -344,8 +392,6 @@ type PartyPanel struct { barY int *d2util.Logger - - testPlayer *d2mapentity.Player } // Load the data for the hero status panel @@ -388,15 +434,6 @@ func (s *PartyPanel) Load() { heroName.Alignment = d2ui.HorizontalAlignCenter s.panelGroup.AddWidget(heroName) - // example data - create an example players and add them - p0 := s.testPlayer - s.AddPlayer(p0, d2enum.PlayerRelationEnemy) - p1 := s.testPlayer - // nolint:gomnd // only test - p1.Stats.Level = 99 - p1.Class = d2enum.HeroNecromancer - s.AddPlayer(p1, d2enum.PlayerRelationFriend) - // create WidgetGroups of party indexes for n, i := range s.partyIndexes { s.indexes[n].AddWidget(i.name) @@ -407,13 +444,6 @@ func (s *PartyPanel) Load() { s.indexes[n].AddWidget(i.level) } - // further test data (to check if DeletePlayer works after creating WG's) - if !s.DeletePlayer(p0) { - s.Warning("cannot remove player: DeletePlayer returned false") - } - - s.AddPlayer(p0, d2enum.PlayerRelationEnemy) - // create bar s.bar, err = s.uiManager.NewSprite(d2resource.PartyBar, d2resource.PaletteSky) if err != nil { @@ -482,7 +512,16 @@ func (s *PartyPanel) SetOnCloseCb(cb func()) { // Advance advances panel func (s *PartyPanel) Advance(_ float64) { - // noop + if !s.IsOpen() { + return + } + + s.UpdatePanel() +} + +// UpdatePlayersList updates internal players list +func (s *PartyPanel) UpdatePlayersList(list map[string]*d2mapentity.Player) { + s.players = list } // nolint:dupl // see quest_log.go.renderStaticPanelFrames comment