diff --git a/d2core/d2asset/asset_manager.go b/d2core/d2asset/asset_manager.go index 11911aef..d710b115 100644 --- a/d2core/d2asset/asset_manager.go +++ b/d2core/d2asset/asset_manager.go @@ -286,7 +286,6 @@ func (am *AssetManager) TranslateString(key string) string { return value } } - // Fix to allow v.setDescLabels("#123") to be bypassed for a patch in issue #360. Reenable later. // log.Panicf("Could not find a string for the key '%s'", key) return key diff --git a/d2core/d2hero/hero_state.go b/d2core/d2hero/hero_state.go index 4f916f1d..d571f1ce 100644 --- a/d2core/d2hero/hero_state.go +++ b/d2core/d2hero/hero_state.go @@ -18,4 +18,5 @@ type HeroState struct { Y float64 `json:"y"` LeftSkill int `json:"leftSkill"` RightSkill int `json:"rightSkill"` + Gold int `json:"Gold"` } diff --git a/d2core/d2map/d2mapentity/factory.go b/d2core/d2map/d2mapentity/factory.go index bc552586..4d449531 100644 --- a/d2core/d2map/d2mapentity/factory.go +++ b/d2core/d2map/d2mapentity/factory.go @@ -64,7 +64,7 @@ func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntit // NewPlayer creates a new player entity and returns a pointer to it. func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero, stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment *d2inventory.CharacterEquipment, - leftSkill, rightSkill int) *Player { + leftSkill, rightSkill int, gold int) *Player { layerEquipment := &[d2enum.CompositeTypeMax]string{ d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(), d2enum.CompositeTypeTorso: equipment.Torso.GetArmorClass(), @@ -101,6 +101,7 @@ func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroT isRunToggled: false, isInTown: true, isRunning: false, + Gold: gold, } result.mapEntity.uuid = id diff --git a/d2core/d2map/d2mapentity/player.go b/d2core/d2map/d2mapentity/player.go index 338044ea..c2d9d84e 100644 --- a/d2core/d2map/d2mapentity/player.go +++ b/d2core/d2map/d2mapentity/player.go @@ -23,6 +23,7 @@ type Player struct { LeftSkill *d2hero.HeroSkill RightSkill *d2hero.HeroSkill Class d2enum.Hero + Gold int lastPathSize int isInTown bool isRunToggled bool diff --git a/d2core/d2ui/button.go b/d2core/d2ui/button.go index 2c1b4dfa..038ff438 100644 --- a/d2core/d2ui/button.go +++ b/d2core/d2ui/button.go @@ -38,9 +38,16 @@ const ( ButtonTypeMinipanelQuest ButtonType = 18 ButtonTypeMinipanelMen ButtonType = 19 ButtonTypeSquareClose ButtonType = 20 - ButtonTypeSkillTreeTab ButtonType = 21 - ButtonTypeMinipanelOpenClose ButtonType = 22 - ButtonTypeMinipanelParty ButtonType = 23 + 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 ButtonNoFixedWidth int = -1 ButtonNoFixedHeight int = -1 @@ -53,7 +60,16 @@ const ( ) const ( + // buyButtonBaseFrame = 2 // base frame offset of the "buy" button dc6 + // sellButtonBaseFrame = 4 // base frame offset of the "sell" button dc6 + // repairButtonBaseFrame = 6 // base frame offset of the "repair" button dc6 + // quaryButtonBaseFrame = 8 // base frame offset of the "quary" button dc6 closeButtonBaseFrame = 10 // base frame offset of the "close" button dc6 + // leftArrowButtonBaseFrame = 12 // base frame offset of the "leftArrow" button dc6 + // rightArrowButtonBaseFrame = 14 // base frame offset of the "rightArrow" button dc6 + okButtonBaseFrame = 16 // base frame offset of the "ok" button dc6 + // repairAllButtonBaseFrame = 18 // base frame offset of the "repair all" button dc6 + // ?AllButtonBaseFrame = 20 // base frame offset of the "?" button dc6 ) const ( @@ -88,6 +104,7 @@ type ButtonLayout struct { const ( buttonTooltipNone int = iota buttonTooltipClose + buttonTooltipOk ) const ( @@ -146,6 +163,10 @@ const ( buttonRunSegmentsY = 1 buttonRunDisabledFrame = -1 + buttonGoldCoinSegmentsX = 1 + buttonGoldCoinSegmentsY = 1 + buttonGoldCoinDisabledFrame = -1 + pressedButtonOffset = 2 ) @@ -238,6 +259,21 @@ func getButtonLayouts() map[ButtonType]ButtonLayout { FixedHeight: ButtonNoFixedHeight, LabelColor: greyAlpha100, }, + ButtonTypeGoldCoin: { + XSegments: buttonGoldCoinSegmentsX, + YSegments: buttonGoldCoinSegmentsY, + DisabledFrame: buttonGoldCoinDisabledFrame, + DisabledColor: lightGreyAlpha75, + ResourceName: d2resource.GoldCoinButton, + PaletteName: d2resource.PaletteSky, + Toggleable: true, + FontPath: d2resource.FontRediculous, + AllowFrameChange: true, + HasImage: true, + FixedWidth: ButtonNoFixedWidth, + FixedHeight: ButtonNoFixedHeight, + LabelColor: greyAlpha100, + }, ButtonTypeSquareClose: { XSegments: buttonBuySellSegmentsX, YSegments: buttonBuySellSegmentsY, @@ -257,6 +293,25 @@ func getButtonLayouts() map[ButtonType]ButtonLayout { TooltipXOffset: buttonCloseTooltipXOffset, TooltipYOffset: buttonCloseTooltipYOffset, }, + ButtonTypeSquareOk: { + XSegments: buttonBuySellSegmentsX, + YSegments: buttonBuySellSegmentsY, + DisabledFrame: buttonBuySellDisabledFrame, + DisabledColor: lightGreyAlpha75, + ResourceName: d2resource.BuySellButton, + PaletteName: d2resource.PaletteUnits, + Toggleable: true, + FontPath: d2resource.Font30, + AllowFrameChange: true, + BaseFrame: okButtonBaseFrame, + HasImage: true, + FixedWidth: ButtonNoFixedWidth, + FixedHeight: ButtonNoFixedHeight, + LabelColor: greyAlpha100, + Tooltip: buttonTooltipOk, + TooltipXOffset: buttonCloseTooltipXOffset, + TooltipYOffset: buttonCloseTooltipYOffset, + }, ButtonTypeSkillTreeTab: { XSegments: buttonSkillTreeTabXSegments, YSegments: buttonSkillTreeTabYSegments, @@ -521,6 +576,9 @@ func (v *Button) createTooltip() { case buttonTooltipClose: t = v.manager.NewTooltip(d2resource.Font16, d2resource.PaletteSky, TooltipXCenter, TooltipYBottom) t.SetText(v.manager.asset.TranslateString("strClose")) + case buttonTooltipOk: + t = v.manager.NewTooltip(d2resource.Font16, d2resource.PaletteSky, TooltipXCenter, TooltipYBottom) + t.SetText(v.manager.asset.TranslateString("#971")) } t.SetVisible(false) diff --git a/d2game/d2gamescreen/character_select.go b/d2game/d2gamescreen/character_select.go index b731cc51..bbbc8015 100644 --- a/d2game/d2gamescreen/character_select.go +++ b/d2game/d2gamescreen/character_select.go @@ -365,6 +365,7 @@ func (v *CharacterSelect) updateCharacterBoxes() { &equipment, v.gameStates[idx].LeftSkill, v.gameStates[idx].RightSkill, + v.gameStates[idx].Gold, ) } } diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index b0d215ed..eb1ca883 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -209,7 +209,7 @@ func NewGameControls( inventoryRecord := asset.Records.Layout.Inventory[inventoryRecordKey] heroStatsPanel := NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, l, hero.Stats) - inventory := NewInventory(asset, ui, l, inventoryRecord) + inventory := NewInventory(asset, ui, l, hero.Gold, inventoryRecord) skilltree := newSkillTree(hero.Skills, hero.Class, asset, l, ui) miniPanel := newMiniPanel(asset, ui, l, isSinglePlayer) diff --git a/d2game/d2player/inventory.go b/d2game/d2player/inventory.go index 980c9afd..88af29a8 100644 --- a/d2game/d2player/inventory.go +++ b/d2game/d2player/inventory.go @@ -1,6 +1,8 @@ package d2player import ( + "fmt" + "github.com/OpenDiablo2/OpenDiablo2/d2core/d2records" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" @@ -21,12 +23,15 @@ const ( const ( invCloseButtonX, invCloseButtonY = 419, 449 + invGoldButtonX, invGoldButtonY = 485, 455 + invGoldLabelX, invGoldLabelY = 510, 455 ) // NewInventory creates an inventory instance and returns a pointer to it func NewInventory(asset *d2asset.AssetManager, ui *d2ui.UIManager, l d2util.LogLevel, + gold int, record *d2records.InventoryRecord) *Inventory { itemTooltip := ui.NewTooltip(d2resource.FontFormal11, d2resource.PaletteStatic, d2ui.TooltipXCenter, d2ui.TooltipYBottom) @@ -42,6 +47,7 @@ func NewInventory(asset *d2asset.AssetManager, itemTooltip: itemTooltip, // originY: record.Panel.Top, originY: 0, // expansion data has these all offset by +60 ... + gold: gold, } inventory.Logger = d2util.NewLogger() @@ -53,32 +59,32 @@ func NewInventory(asset *d2asset.AssetManager, // Inventory represents the inventory type Inventory struct { - asset *d2asset.AssetManager - item *diablo2item.ItemFactory - uiManager *d2ui.UIManager - frame *d2ui.UIFrame - panel *d2ui.Sprite - grid *ItemGrid - itemTooltip *d2ui.Tooltip - closeButton *d2ui.Button - hoverX int - hoverY int - originX int - originY int - lastMouseX int - lastMouseY int - hovering bool - isOpen bool - onCloseCb func() + asset *d2asset.AssetManager + item *diablo2item.ItemFactory + uiManager *d2ui.UIManager + frame *d2ui.UIFrame + panel *d2ui.Sprite + grid *ItemGrid + itemTooltip *d2ui.Tooltip + closeButton *d2ui.Button + goldButton *d2ui.Button + goldLabel *d2ui.Label + panelGroup *d2ui.WidgetGroup + panelMoveGold *d2ui.WidgetGroup + hoverX int + hoverY int + originX int + originY int + lastMouseX int + lastMouseY int + hovering bool + isOpen bool + onCloseCb func() + gold int *d2util.Logger } -// IsOpen returns true if the inventory is open -func (g *Inventory) IsOpen() bool { - return g.isOpen -} - // Toggle negates the open state of the inventory func (g *Inventory) Toggle() { if g.isOpen { @@ -88,34 +94,42 @@ func (g *Inventory) Toggle() { } } -// Open opens the inventory -func (g *Inventory) Open() { - g.isOpen = true - g.closeButton.SetVisible(true) -} - -// Close closes the inventory -func (g *Inventory) Close() { - g.isOpen = false - g.closeButton.SetVisible(false) - g.onCloseCb() -} - -// SetOnCloseCb the callback run on closing the inventory -func (g *Inventory) SetOnCloseCb(cb func()) { - g.onCloseCb = cb -} - // Load the resources required by the inventory func (g *Inventory) Load() { + var err error + + g.panelGroup = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel) + g.panelMoveGold = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel) + g.frame = d2ui.NewUIFrame(g.asset, g.uiManager, d2ui.FrameRight) + g.panelGroup.AddWidget(g.frame) g.closeButton = g.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "") g.closeButton.SetVisible(false) g.closeButton.SetPosition(invCloseButtonX, invCloseButtonY) g.closeButton.OnActivated(func() { g.Close() }) + g.panelGroup.AddWidget(g.closeButton) - g.panel, _ = g.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky) + g.goldButton = g.uiManager.NewButton(d2ui.ButtonTypeGoldCoin, "") + g.goldButton.SetVisible(false) + g.goldButton.SetPosition(invGoldButtonX, invGoldButtonY) + g.goldButton.OnActivated(func() { g.onGoldClicked() }) + g.panelGroup.AddWidget(g.goldButton) + + g.goldLabel = g.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteStatic) + g.goldLabel.Alignment = d2ui.HorizontalAlignLeft + g.goldLabel.SetText(fmt.Sprintln(g.gold)) + g.goldLabel.SetPosition(invGoldLabelX, invGoldLabelY) + g.panelGroup.AddWidget(g.goldLabel) + + g.goldButton = g.uiManager.NewButton(d2ui.ButtonTypeGoldCoin, "") + + g.panel, err = g.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky) + if err != nil { + g.Error(err.Error()) + } + + g.panelGroup.SetVisible(false) // https://github.com/OpenDiablo2/OpenDiablo2/issues/795 testInventoryCodes := [][]string{ @@ -128,8 +142,8 @@ func (g *Inventory) Load() { inventoryItems := make([]InventoryItem, 0) for idx := range testInventoryCodes { - item, err := g.item.NewItem(testInventoryCodes[idx]...) - if err != nil { + item, itemErr := g.item.NewItem(testInventoryCodes[idx]...) + if itemErr != nil { continue } @@ -152,26 +166,55 @@ func (g *Inventory) Load() { } for slot := range testEquippedItemCodes { - item, err := g.item.NewItem(testEquippedItemCodes[slot]...) - if err != nil { + item, itemErr := g.item.NewItem(testEquippedItemCodes[slot]...) + if itemErr != nil { continue } g.grid.ChangeEquippedSlot(slot, item) } - _, err := g.grid.Add(inventoryItems...) + _, err = g.grid.Add(inventoryItems...) if err != nil { g.Errorf("could not add items to the inventory, err: %v", err.Error()) } } +// Open opens the inventory +func (g *Inventory) Open() { + g.isOpen = true + g.panelGroup.SetVisible(true) +} + +// Close closes the inventory +func (g *Inventory) Close() { + g.isOpen = false + g.panelGroup.SetVisible(false) + g.onCloseCb() +} + +// SetOnCloseCb the callback run on closing the inventory +func (g *Inventory) SetOnCloseCb(cb func()) { + g.onCloseCb = cb +} + +func (g *Inventory) onGoldClicked() { + g.Info("Gold action clicked") +} + +// IsOpen returns true if the inventory is open +func (g *Inventory) IsOpen() bool { + return g.isOpen +} + // Render draws the inventory onto the given surface func (g *Inventory) Render(target d2interface.Surface) { if !g.isOpen { return } + g.goldLabel.Render(target) + err := g.renderFrame(target) if err != nil { g.Error(err.Error()) diff --git a/d2networking/d2client/game_client.go b/d2networking/d2client/game_client.go index 5bc8bbe1..dab59ca1 100644 --- a/d2networking/d2client/game_client.go +++ b/d2networking/d2client/game_client.go @@ -220,7 +220,7 @@ func (g *GameClient) handleAddPlayerPacket(packet d2netpacket.NetPacket) error { d2hero.HydrateSkills(player.Skills, g.asset) newPlayer := g.MapEngine.NewPlayer(player.ID, player.Name, player.X, player.Y, 0, - player.HeroType, player.Stats, player.Skills, &player.Equipment, player.LeftSkill, player.RightSkill) + player.HeroType, player.Stats, player.Skills, &player.Equipment, player.LeftSkill, player.RightSkill, player.Gold) g.Players[newPlayer.ID()] = newPlayer g.MapEngine.AddEntity(newPlayer) diff --git a/d2networking/d2netpacket/packet_add_player.go b/d2networking/d2netpacket/packet_add_player.go index c3aa024a..130572ca 100644 --- a/d2networking/d2netpacket/packet_add_player.go +++ b/d2networking/d2netpacket/packet_add_player.go @@ -24,13 +24,20 @@ type AddPlayerPacket struct { Skills map[int]*d2hero.HeroSkill `json:"heroSkills"` LeftSkill int `json:"leftSkill"` RightSkill int `json:"rightSkill"` + Gold int } // CreateAddPlayerPacket returns a NetPacket which declares an // AddPlayerPacket with the data in given parameters. -func CreateAddPlayerPacket(id, name string, x, y int, heroType d2enum.Hero, - stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment d2inventory.CharacterEquipment, - leftSkill, rightSkill int) NetPacket { +func CreateAddPlayerPacket( + id, name string, + x, y int, + heroType d2enum.Hero, + stats *d2hero.HeroStatsState, + skills map[int]*d2hero.HeroSkill, + equipment d2inventory.CharacterEquipment, + leftSkill, rightSkill int, + gold int) NetPacket { addPlayerPacket := AddPlayerPacket{ ID: id, Name: name, @@ -42,6 +49,7 @@ func CreateAddPlayerPacket(id, name string, x, y int, heroType d2enum.Hero, Skills: skills, LeftSkill: leftSkill, RightSkill: rightSkill, + Gold: gold, } b, err := json.Marshal(addPlayerPacket) diff --git a/d2networking/d2server/game_server.go b/d2networking/d2server/game_server.go index 47cbdde2..fbec2c30 100644 --- a/d2networking/d2server/game_server.go +++ b/d2networking/d2server/game_server.go @@ -376,6 +376,7 @@ func (g *GameServer) handleClientConnection(client ClientConnection, x, y float6 playerState.Equipment, playerState.LeftSkill, playerState.RightSkill, + playerState.Gold, ) for _, connection := range g.connections { @@ -403,6 +404,7 @@ func (g *GameServer) handleClientConnection(client ClientConnection, x, y float6 conPlayerState.Equipment, conPlayerState.LeftSkill, conPlayerState.RightSkill, + conPlayerState.Gold, ), )