mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-18 14:36:44 -05:00
* quest log disabled icon
* removed unused functions for text colorizing
* terminal printing
* fixed saving key change bug
* help overlay text
* removed unused issue comments
* Update Ebiten to v2.0.2
* changed terminal color separator & changed logLevelNone to logLevelDefault in app.go
* status and screens update
* quest animation initial.
* escape menu hotkeys
* hero save file
* add-buttons init
* add-buttons actions
* stats changing: hero stats panel
* skill tre - remaining points label
* revert:hero save file (app.go)
* escape menu hotkeys
* hero save file
* updated d2hero.HeroStatsState
* corrected grammar errors
* animation is played and last frame is completedFrame
* animation stops playing, when quest log is closed & quest socket gets highlighted, when animation is playing & fixed highlight bug
* fixed quest descr bug & added code description
* level-up buttons tooltips
* Replaced kingping with flag package
* Cleanup d2records logging
* Renamed CharStatRecord
* Renamed SoundDetailRecord
* Renamed MonStatRecord
* Renamed ObjectDetailRecord
* Renamed MonStat2Record
* fixed onHover bug in d2ui.Sprite (#992)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
* added static checks to d2ui (#990)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
* fixed onHover bug in d2ui.Label (#991)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
* Revert "fixed onHover bug in d2ui.Sprite"
This reverts commit 8b557062fb
.
* tip-labels in tcpip menu
* skill select menu dependencies (when we open skillselect menu, other panels are closed)
* Cleaned up d2term
* A wild } appeared
* Fixed linter issues
* ckecked value of italian modifier
* game-controls refactor
* fixed build and lint errors
* removed unnecessary switch-case statments from onKeyUp and onEscKey
* fixed bug with terminal's logLevel
* Refactor StreamWriter
* Refactor StreamReader
* Fixed gocritic linter issues
* Reduce GetTiles slice allocation
* Networking bugfixes and cleanup
Make sure connections close properly, without weird error messages
Remove player map entity when a player disconnects from a multiplayer game
Close server properly when host disconnects, handle ServerClose on remote clients
Don't mix JSON decoders and raw TCP writes
Actually handle incoming packets from remote clients
General code cleanup for simplicity and consistency
* Switched to self hosted build agent
* Removed PR requirement for action
* remove build job requirement
* Fiddling with actions names
* Updated workflows
* Fix yaml errors
* Yet another yaml fix
* Removed improper ebiten dependency in d2interface.
* Add checkboxes, checkbox test scene
* Render HUD before Panels (in this Case 'Panels' only does mean Inventory Panel). This is to avoid Entity Labels to be renderd above the Inventory Panel. Fixes #936
* This DCC frame size calculation seems useless
TBH there some to be some other overcomplicated things going on in
DCCAnimation but too tired to use brain right now.
* De-lint ecs branch
* bugfix: file_handle_resolver
* Add boot state to scenes, fix loading screen scene
* added label-button widget (#989)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
* removed links to closed issues from code (#1005)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
Co-authored-by: gravestench <dknuth0101@gmail.com>
* removed unused fields from d2player.GameControl.actionableRegions (#997)
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
Co-authored-by: gravestench <dknuth0101@gmail.com>
* d2ui.Frame refactor (#994)
* d2ui.Frame refactor
* removed unneccessery d2asset.AssetManager argument from d2ui.NewUIFrame
* d2ui.Frame refactor
* removed unneccessery d2asset.AssetManager argument from d2ui.NewUIFrame
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
Co-authored-by: Tim Sarbin <tim.sarbin@gmail.com>
Co-authored-by: gravestench <dknuth0101@gmail.com>
* d2mpq refactored (#1020)
* d2mpq refactor
* d2mpq refactor last standing lint error
* d2mpq refactor: less linter noise
* d2mpq refactor: more linter issues
Co-authored-by: M. Sz <mszeptuch@protonmail.com>
Co-authored-by: Tim Sarbin <tim.sarbin@gmail.com>
Co-authored-by: Hajime Hoshi <hajimehoshi@gmail.com>
Co-authored-by: gucio321 <73652197+gucio321@users.noreply.github.com>
Co-authored-by: Intyre <intyre@gmail.com>
Co-authored-by: ThomasChr <thomaschristlieb@hotmail.com>
Co-authored-by: Ziemas <ziemas@ziemas.se>
Co-authored-by: gravestench <dknuth0101@gmail.com>
326 lines
8.2 KiB
Go
326 lines
8.2 KiB
Go
package d2player
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
"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/d2item/diablo2item"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
|
)
|
|
|
|
const (
|
|
frameInventoryTopLeft = 4
|
|
frameInventoryTopRight = 5
|
|
frameInventoryBottomLeft = 6
|
|
frameInventoryBottomRight = 7
|
|
)
|
|
|
|
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, error) {
|
|
itemTooltip := ui.NewTooltip(d2resource.FontFormal11, d2resource.PaletteStatic, d2ui.TooltipXCenter, d2ui.TooltipYBottom)
|
|
|
|
itemFactory, err := diablo2item.NewItemFactory(asset)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("during creating new item factory: %s", err)
|
|
}
|
|
|
|
mgp := NewMoveGoldPanel(asset, ui, gold, l)
|
|
|
|
inventory := &Inventory{
|
|
asset: asset,
|
|
uiManager: ui,
|
|
item: itemFactory,
|
|
grid: NewItemGrid(asset, ui, l, record),
|
|
originX: record.Panel.Left,
|
|
itemTooltip: itemTooltip,
|
|
// originY: record.Panel.Top,
|
|
originY: 0, // expansion data has these all offset by +60 ...
|
|
gold: gold,
|
|
moveGoldPanel: mgp,
|
|
}
|
|
|
|
inventory.moveGoldPanel.SetOnCloseCb(func() { inventory.onCloseGoldPanel() })
|
|
|
|
inventory.Logger = d2util.NewLogger()
|
|
inventory.Logger.SetLevel(l)
|
|
inventory.Logger.SetPrefix(logPrefix)
|
|
|
|
return inventory, nil
|
|
}
|
|
|
|
// Inventory represents the inventory
|
|
type Inventory struct {
|
|
asset *d2asset.AssetManager
|
|
item *diablo2item.ItemFactory
|
|
uiManager *d2ui.UIManager
|
|
panel *d2ui.Sprite
|
|
goldLabel *d2ui.Label
|
|
grid *ItemGrid
|
|
itemTooltip *d2ui.Tooltip
|
|
panelGroup *d2ui.WidgetGroup
|
|
hoverX int
|
|
hoverY int
|
|
originX int
|
|
originY int
|
|
lastMouseX int
|
|
lastMouseY int
|
|
hovering bool
|
|
isOpen bool
|
|
onCloseCb func()
|
|
gold int
|
|
moveGoldPanel *MoveGoldPanel
|
|
|
|
*d2util.Logger
|
|
}
|
|
|
|
// Toggle negates the open state of the inventory
|
|
func (g *Inventory) Toggle() {
|
|
if g.isOpen {
|
|
g.Close()
|
|
} else {
|
|
g.Open()
|
|
}
|
|
}
|
|
|
|
// Load the resources required by the inventory
|
|
func (g *Inventory) Load() {
|
|
var err error
|
|
|
|
g.panelGroup = g.uiManager.NewWidgetGroup(d2ui.RenderPriorityInventory)
|
|
|
|
frame := g.uiManager.NewUIFrame(d2ui.FrameRight)
|
|
g.panelGroup.AddWidget(frame)
|
|
|
|
g.panel, err = g.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
|
if err != nil {
|
|
g.Error(err.Error())
|
|
}
|
|
|
|
closeButton := g.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
|
closeButton.SetVisible(false)
|
|
closeButton.SetPosition(invCloseButtonX, invCloseButtonY)
|
|
closeButton.OnActivated(func() { g.Close() })
|
|
g.panelGroup.AddWidget(closeButton)
|
|
|
|
goldButton := g.uiManager.NewButton(d2ui.ButtonTypeGoldCoin, "")
|
|
goldButton.SetVisible(false)
|
|
goldButton.SetPosition(invGoldButtonX, invGoldButtonY)
|
|
goldButton.OnActivated(func() { g.onGoldClicked() })
|
|
|
|
// nolint:gocritic // this variable will be used in future
|
|
// deposite := g.asset.TranslateString("strGoldDeposit")
|
|
drop := g.asset.TranslateString("strGoldDrop")
|
|
// nolint:gocritic // this variable will be used in future
|
|
// withdraw := g.asset.TranslateString("strGoldWithdraw")
|
|
|
|
tooltip := g.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteSky, d2ui.TooltipXCenter, d2ui.TooltipYBottom)
|
|
// here should be switch-case statement for each of move-gold button descr
|
|
tooltip.SetText(drop)
|
|
tooltip.SetPosition(invGoldButtonX, invGoldButtonY)
|
|
goldButton.SetTooltip(tooltip)
|
|
|
|
g.panelGroup.AddWidget(goldButton)
|
|
|
|
g.goldLabel = g.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteStatic)
|
|
g.goldLabel.Alignment = d2ui.HorizontalAlignLeft
|
|
g.goldLabel.SetText(fmt.Sprintln(g.moveGoldPanel.gold))
|
|
g.goldLabel.SetPosition(invGoldLabelX, invGoldLabelY)
|
|
g.panelGroup.AddWidget(g.goldLabel)
|
|
|
|
// https://github.com/OpenDiablo2/OpenDiablo2/issues/795
|
|
testInventoryCodes := [][]string{
|
|
{"kit", "Crimson", "of the Bat", "of Frost"},
|
|
{"rin", "Steel", "of Shock"},
|
|
{"jav"},
|
|
{"buc"},
|
|
}
|
|
|
|
inventoryItems := make([]InventoryItem, 0)
|
|
|
|
for idx := range testInventoryCodes {
|
|
item, itemErr := g.item.NewItem(testInventoryCodes[idx]...)
|
|
if itemErr != nil {
|
|
continue
|
|
}
|
|
|
|
item.Identify()
|
|
inventoryItems = append(inventoryItems, item)
|
|
}
|
|
|
|
// https://github.com/OpenDiablo2/OpenDiablo2/issues/795
|
|
testEquippedItemCodes := map[d2enum.EquippedSlot][]string{
|
|
d2enum.EquippedSlotLeftArm: {"wnd"},
|
|
d2enum.EquippedSlotRightArm: {"buc"},
|
|
d2enum.EquippedSlotHead: {"crn"},
|
|
d2enum.EquippedSlotTorso: {"plt"},
|
|
d2enum.EquippedSlotLegs: {"vbt"},
|
|
d2enum.EquippedSlotBelt: {"vbl"},
|
|
d2enum.EquippedSlotGloves: {"lgl"},
|
|
d2enum.EquippedSlotLeftHand: {"rin"},
|
|
d2enum.EquippedSlotRightHand: {"rin"},
|
|
d2enum.EquippedSlotNeck: {"amu"},
|
|
}
|
|
|
|
for slot := range testEquippedItemCodes {
|
|
item, itemErr := g.item.NewItem(testEquippedItemCodes[slot]...)
|
|
if itemErr != nil {
|
|
continue
|
|
}
|
|
|
|
g.grid.ChangeEquippedSlot(slot, item)
|
|
}
|
|
|
|
_, err = g.grid.Add(inventoryItems...)
|
|
if err != nil {
|
|
g.Errorf("could not add items to the inventory, err: %v", err.Error())
|
|
}
|
|
|
|
g.moveGoldPanel.Load()
|
|
|
|
g.panelGroup.SetVisible(false)
|
|
}
|
|
|
|
// 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.moveGoldPanel.Close()
|
|
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("Move gold action clicked")
|
|
g.toggleMoveGoldPanel()
|
|
}
|
|
|
|
func (g *Inventory) toggleMoveGoldPanel() {
|
|
g.moveGoldPanel.Toggle()
|
|
}
|
|
|
|
func (g *Inventory) onCloseGoldPanel() {
|
|
|
|
}
|
|
|
|
// IsOpen returns true if the inventory is open
|
|
func (g *Inventory) IsOpen() bool {
|
|
return g.isOpen
|
|
}
|
|
|
|
// Advance advances the state of the Inventory
|
|
func (g *Inventory) Advance(_ float64) {
|
|
if !g.IsOpen() {
|
|
return
|
|
}
|
|
|
|
g.goldLabel.SetText(fmt.Sprintln(g.moveGoldPanel.gold))
|
|
}
|
|
|
|
// Render draws the inventory onto the given surface
|
|
func (g *Inventory) Render(target d2interface.Surface) {
|
|
if !g.isOpen {
|
|
return
|
|
}
|
|
|
|
g.renderFrame(target)
|
|
|
|
g.grid.Render(target)
|
|
g.renderItemHover(target)
|
|
}
|
|
|
|
func (g *Inventory) renderFrame(target d2interface.Surface) {
|
|
frames := []int{
|
|
frameInventoryTopLeft,
|
|
frameInventoryTopRight,
|
|
frameInventoryBottomRight,
|
|
frameInventoryBottomLeft,
|
|
}
|
|
|
|
x, y := g.originX+1, g.originY
|
|
y += 64
|
|
|
|
for _, frame := range frames {
|
|
if err := g.panel.SetCurrentFrame(frame); err != nil {
|
|
g.Error(err.Error())
|
|
return
|
|
}
|
|
|
|
w, h := g.panel.GetCurrentFrameSize()
|
|
|
|
g.panel.SetPosition(x, y+h)
|
|
g.panel.Render(target)
|
|
|
|
switch frame {
|
|
case frameInventoryTopLeft:
|
|
x += w
|
|
case frameInventoryTopRight:
|
|
y += h
|
|
case frameInventoryBottomRight:
|
|
x = g.originX + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *Inventory) renderItemHover(target d2interface.Surface) {
|
|
hovering := false
|
|
|
|
for idx := range g.grid.items {
|
|
item := g.grid.items[idx]
|
|
ix, iy := g.grid.SlotToScreen(item.InventoryGridSlot())
|
|
iw, ih := g.grid.sprites[item.GetItemCode()].GetCurrentFrameSize()
|
|
mx, my := g.lastMouseX, g.lastMouseY
|
|
hovering = hovering || ((mx > ix) && (mx < ix+iw) && (my > iy) && (my < iy+ih))
|
|
|
|
if hovering {
|
|
if !g.hovering {
|
|
// set the initial hover coordinates
|
|
// this is so that moving mouse doesnt move the description
|
|
g.hoverX, g.hoverY = mx, my
|
|
}
|
|
|
|
g.renderItemDescription(target, item)
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
g.hovering = hovering
|
|
}
|
|
|
|
func (g *Inventory) renderItemDescription(target d2interface.Surface, i InventoryItem) {
|
|
if !g.moveGoldPanel.IsOpen() {
|
|
lines := i.GetItemDescription()
|
|
g.itemTooltip.SetTextLines(lines)
|
|
_, y := g.grid.SlotToScreen(i.InventoryGridSlot())
|
|
|
|
g.itemTooltip.SetPosition(g.hoverX, y)
|
|
g.itemTooltip.Render(target)
|
|
}
|
|
}
|