1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-27 09:35:29 +00:00

Merge pull request #15 from gucio321/master

update
This commit is contained in:
gucio321 2020-12-17 15:10:25 +01:00 committed by GitHub
commit 84cac0d181
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 232 additions and 61 deletions

View File

@ -25,7 +25,8 @@ ALL OTHER TRADEMARKS ARE THE PROPERTY OF THEIR RESPECTIVE OWNERS.
## Status ## Status
At the moment (october 2020) the game starts, you can select any character and run around Act1 town. At the moment (december 2020) the game starts, you can select any character and run around Act1 town.
You can also open any of the game's panels.
Much work has been made in the background, but a lot of work still has to be done for the game to be playable. Much work has been made in the background, but a lot of work still has to be done for the game to be playable.
@ -128,6 +129,8 @@ which will be updated over time with new requirements.
![Inventory Window](docs/Inventory.png) ![Inventory Window](docs/Inventory.png)
![Game Panels](docs/game_panels.png)
## Additional Credits ## Additional Credits
- Diablo2 Logo - Diablo2 Logo

View File

@ -245,6 +245,8 @@ const (
Frame = "/data/global/ui/PANEL/800borderframe.dc6" Frame = "/data/global/ui/PANEL/800borderframe.dc6"
InventoryCharacterPanel = "/data/global/ui/PANEL/invchar6.DC6" InventoryCharacterPanel = "/data/global/ui/PANEL/invchar6.DC6"
HeroStatsPanelStatsPoints = "/data/global/ui/PANEL/skillpoints.dc6"
HeroStatsPanelSocket = "/data/global/ui/PANEL/levelsocket.dc6"
InventoryWeaponsTab = "/data/global/ui/PANEL/invchar6Tab.DC6" InventoryWeaponsTab = "/data/global/ui/PANEL/invchar6Tab.DC6"
SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6" SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6"
SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6" SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6"

View File

@ -10,27 +10,22 @@ type HeroStatsState struct {
Level int `json:"level"` Level int `json:"level"`
Experience int `json:"experience"` Experience int `json:"experience"`
Vitality int `json:"vitality"`
Energy int `json:"energy"`
Strength int `json:"strength"` Strength int `json:"strength"`
Energy int `json:"energy"`
Dexterity int `json:"dexterity"` Dexterity int `json:"dexterity"`
Vitality int `json:"vitality"`
// there are stats and skills points remaining to add.
StatsPoints int `json:"statsPoints"`
SkillPoints int `json:"skillPoints"`
AttackRating int `json:"attackRating"`
DefenseRating int `json:"defenseRating"`
MaxStamina int `json:"maxStamina"`
Health int `json:"health"` Health int `json:"health"`
MaxHealth int `json:"maxHealth"` MaxHealth int `json:"maxHealth"`
Mana int `json:"mana"` Mana int `json:"mana"`
MaxMana int `json:"maxMana"` MaxMana int `json:"maxMana"`
Stamina float64 `json:"-"` // only MaxStamina is saved, Stamina gets reset on entering world
FireResistance int `json:"fireResistance"` MaxStamina int `json:"maxStamina"`
ColdResistance int `json:"coldResistance"`
LightningResistance int `json:"lightningResistance"`
PoisonResistance int `json:"poisonResistance"`
// values which are not saved/loaded(computed) // values which are not saved/loaded(computed)
Stamina float64 `json:"-"` // only MaxStamina is saved, Stamina gets reset on entering world
NextLevelExp int `json:"-"` NextLevelExp int `json:"-"`
} }
@ -44,6 +39,8 @@ func (f *HeroStateFactory) CreateHeroStatsState(heroClass d2enum.Hero, classStat
Dexterity: classStats.InitDex, Dexterity: classStats.InitDex,
Vitality: classStats.InitVit, Vitality: classStats.InitVit,
Energy: classStats.InitEne, Energy: classStats.InitEne,
StatsPoints: 0,
SkillPoints: 0,
MaxHealth: classStats.InitVit * classStats.LifePerVit, MaxHealth: classStats.InitVit * classStats.LifePerVit,
MaxMana: classStats.InitEne * classStats.ManaPerEne, MaxMana: classStats.InitEne * classStats.ManaPerEne,

View File

@ -55,6 +55,7 @@ const (
ButtonTypeSquelchChat ButtonType = 35 ButtonTypeSquelchChat ButtonType = 35
ButtonTypeTabBlank ButtonType = 36 ButtonTypeTabBlank ButtonType = 36
ButtonTypeBlankQuestBtn ButtonType = 37 ButtonTypeBlankQuestBtn ButtonType = 37
ButtonTypeAddSkill ButtonType = 38
ButtonNoFixedWidth int = -1 ButtonNoFixedWidth int = -1
ButtonNoFixedHeight int = -1 ButtonNoFixedHeight int = -1
@ -199,6 +200,10 @@ const (
buttonGoldCoinSegmentsY = 1 buttonGoldCoinSegmentsY = 1
buttonGoldCoinDisabledFrame = -1 buttonGoldCoinDisabledFrame = -1
buttonAddSkillSegmentsX = 1
buttonAddSkillSegmentsY = 1
buttonAddSkillDisabledFrame = 2
pressedButtonOffset = 2 pressedButtonOffset = 2
) )
@ -746,6 +751,20 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
FixedHeight: ButtonNoFixedHeight, FixedHeight: ButtonNoFixedHeight,
LabelColor: whiteAlpha100, LabelColor: whiteAlpha100,
}, },
ButtonTypeAddSkill: {
XSegments: buttonAddSkillSegmentsX,
YSegments: buttonAddSkillSegmentsY,
DisabledFrame: buttonAddSkillDisabledFrame,
DisabledColor: whiteAlpha100,
ResourceName: d2resource.AddSkillButton,
PaletteName: d2resource.PaletteSky,
Toggleable: true,
FontPath: d2resource.Font16,
AllowFrameChange: true,
HasImage: true,
FixedWidth: ButtonNoFixedWidth,
FixedHeight: ButtonNoFixedHeight,
},
} }
} }

View File

@ -214,7 +214,7 @@ func NewGameControls(
return nil, err return nil, err
} }
skilltree := newSkillTree(hero.Skills, hero.Class, asset, l, ui) skilltree := newSkillTree(hero.Skills, hero.Class, hero.Stats, asset, l, ui)
miniPanel := newMiniPanel(asset, ui, l, isSinglePlayer) miniPanel := newMiniPanel(asset, ui, l, isSinglePlayer)
@ -224,13 +224,9 @@ func NewGameControls(
} }
helpOverlay := NewHelpOverlay(asset, ui, l, keyMap) helpOverlay := NewHelpOverlay(asset, ui, l, keyMap)
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, mapRenderer)
const blackAlpha50percent = 0x0000007f const blackAlpha50percent = 0x0000007f
hoverLabel := hud.nameLabel
hoverLabel.SetBackgroundColor(d2util.Color(blackAlpha50percent))
gc := &GameControls{ gc := &GameControls{
asset: asset, asset: asset,
ui: ui, ui: ui,
@ -246,7 +242,6 @@ func NewGameControls(
questLog: questLog, questLog: questLog,
HelpOverlay: helpOverlay, HelpOverlay: helpOverlay,
keyMap: keyMap, keyMap: keyMap,
hud: hud,
bottomMenuRect: &d2geom.Rectangle{ bottomMenuRect: &d2geom.Rectangle{
Left: menuBottomRectX, Left: menuBottomRectX,
Top: menuBottomRectY, Top: menuBottomRectY,
@ -271,6 +266,12 @@ func NewGameControls(
isSinglePlayer: isSinglePlayer, isSinglePlayer: isSinglePlayer,
} }
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, gc, mapRenderer)
gc.hud = hud
hoverLabel := hud.nameLabel
hoverLabel.SetBackgroundColor(d2util.Color(blackAlpha50percent))
gc.heroStatsPanel.SetOnCloseCb(gc.onCloseHeroStatsPanel) gc.heroStatsPanel.SetOnCloseCb(gc.onCloseHeroStatsPanel)
gc.questLog.SetOnCloseCb(gc.onCloseQuestLog) gc.questLog.SetOnCloseCb(gc.onCloseQuestLog)
gc.inventory.SetOnCloseCb(gc.onCloseInventory) gc.inventory.SetOnCloseCb(gc.onCloseInventory)
@ -713,6 +714,9 @@ func (g *GameControls) Load() {
g.questLog.Load() g.questLog.Load()
g.HelpOverlay.Load() g.HelpOverlay.Load()
g.loadAddButtons()
g.setAddButtons()
miniPanelActions := &miniPanelActions{ miniPanelActions := &miniPanelActions{
characterToggle: g.toggleHeroStatsPanel, characterToggle: g.toggleHeroStatsPanel,
inventoryToggle: g.toggleInventoryPanel, inventoryToggle: g.toggleInventoryPanel,
@ -733,6 +737,10 @@ func (g *GameControls) Advance(elapsed float64) error {
return err return err
} }
if g.heroStatsPanel.IsOpen() || g.skilltree.IsOpen() {
g.setAddButtons()
}
return nil return nil
} }
@ -1099,3 +1107,13 @@ func (g *GameControls) bindTerminalCommands(term d2interface.Terminal) error {
return nil return nil
} }
func (g *GameControls) setAddButtons() {
g.hud.addStatsButton.SetEnabled(g.hero.Stats.StatsPoints > 0)
g.hud.addSkillButton.SetEnabled(g.hero.Stats.SkillPoints > 0)
}
func (g *GameControls) loadAddButtons() {
g.hud.addStatsButton.OnActivated(func() { g.toggleHeroStatsPanel() })
g.hud.addSkillButton.OnActivated(func() { g.toggleSkilltreePanel() })
}

View File

@ -9,6 +9,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
@ -55,6 +56,15 @@ const (
const ( const (
heroStatsCloseButtonX, heroStatsCloseButtonY = 208, 453 heroStatsCloseButtonX, heroStatsCloseButtonY = 208, 453
addStatSocketOffsetX, addStatSocketOffsetY = -3, 34
)
const (
newStatsRemainingPointsFieldX, newStatsRemainingPointsFieldY = 83, 430
newStatsRemainingPointsLabelX = 92
newStatsRemainingPointsLabel1Y = 411
newStatsRemainingPointsLabel2Y = 418
newStatsRemainingPointsValueX, newStatsRemainingPointsValueY = 188, 411
) )
// PanelText represents text on the panel // PanelText represents text on the panel
@ -122,6 +132,8 @@ type HeroStatsPanel struct {
labels *StatsPanelLabels labels *StatsPanelLabels
onCloseCb func() onCloseCb func()
panelGroup *d2ui.WidgetGroup panelGroup *d2ui.WidgetGroup
newStatPoints *d2ui.WidgetGroup
remainingPoints *d2ui.Label
originX int originX int
originY int originY int
@ -135,6 +147,7 @@ func (s *HeroStatsPanel) Load() {
var err error var err error
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel) s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
s.newStatPoints = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft) frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
s.panelGroup.AddWidget(frame) s.panelGroup.AddWidget(frame)
@ -154,10 +167,91 @@ func (s *HeroStatsPanel) Load() {
closeButton.OnActivated(func() { s.Close() }) closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(closeButton) s.panelGroup.AddWidget(closeButton)
s.loadNewStatPoints()
s.setLayout()
s.initStatValueLabels() s.initStatValueLabels()
s.panelGroup.SetVisible(false) s.panelGroup.SetVisible(false)
} }
func (s *HeroStatsPanel) loadNewStatPoints() {
field, err := s.uiManager.NewSprite(d2resource.HeroStatsPanelStatsPoints, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
field.SetPosition(newStatsRemainingPointsFieldX, newStatsRemainingPointsFieldY)
s.newStatPoints.AddWidget(field)
label1 := s.uiManager.NewLabel(d2resource.Font6, d2resource.PaletteSky)
label1.SetPosition(newStatsRemainingPointsLabelX, newStatsRemainingPointsLabel1Y)
label1.SetText(s.asset.TranslateString("strchrstat"))
label1.Color[0] = d2util.Color(d2gui.ColorRed)
s.newStatPoints.AddWidget(label1)
label2 := s.uiManager.NewLabel(d2resource.Font6, d2resource.PaletteSky)
label2.SetPosition(newStatsRemainingPointsLabelX, newStatsRemainingPointsLabel2Y)
label2.SetText(s.asset.TranslateString("strchrrema"))
label2.Color[0] = d2util.Color(d2gui.ColorRed)
s.newStatPoints.AddWidget(label2)
s.remainingPoints = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
s.remainingPoints.SetText(strconv.Itoa(s.heroState.StatsPoints))
s.remainingPoints.SetPosition(newStatsRemainingPointsValueX, newStatsRemainingPointsValueY)
s.remainingPoints.Alignment = d2ui.HorizontalAlignCenter
s.newStatPoints.AddWidget(s.remainingPoints)
buttons := []struct {
x int
y int
cb func()
}{
{205, 140, func() {
s.heroState.Strength++
}},
{205, 201, func() {
s.heroState.Dexterity++
}},
{205, 286, func() {
s.heroState.Vitality++
}},
{205, 347, func() {
s.heroState.Energy++
}},
}
var socket *d2ui.Sprite
var button *d2ui.Button
for _, i := range buttons {
currentValue := i
socket, err = s.uiManager.NewSprite(d2resource.HeroStatsPanelSocket, d2resource.PaletteSky)
if err != nil {
s.Error(err.Error())
}
socket.SetPosition(i.x+addStatSocketOffsetX, i.y+addStatSocketOffsetY)
s.newStatPoints.AddWidget(socket)
button = s.uiManager.NewButton(d2ui.ButtonTypeAddSkill, d2resource.PaletteSky)
button.SetPosition(i.x, i.y)
button.OnActivated(func() {
currentValue.cb()
s.heroState.StatsPoints--
s.remainingPoints.SetText(strconv.Itoa(s.heroState.StatsPoints))
s.setStatValues()
s.setLayout()
})
s.newStatPoints.AddWidget(button)
}
}
func (s *HeroStatsPanel) setLayout() {
s.newStatPoints.SetVisible(s.heroState.StatsPoints > 0 && s.IsOpen())
}
// IsOpen returns true if the hero status panel is open // IsOpen returns true if the hero status panel is open
func (s *HeroStatsPanel) IsOpen() bool { func (s *HeroStatsPanel) IsOpen() bool {
return s.isOpen return s.isOpen
@ -176,12 +270,14 @@ func (s *HeroStatsPanel) Toggle() {
func (s *HeroStatsPanel) Open() { func (s *HeroStatsPanel) Open() {
s.isOpen = true s.isOpen = true
s.panelGroup.SetVisible(true) s.panelGroup.SetVisible(true)
s.setLayout()
} }
// Close closed the hero status panel // Close closed the hero status panel
func (s *HeroStatsPanel) Close() { func (s *HeroStatsPanel) Close() {
s.isOpen = false s.isOpen = false
s.panelGroup.SetVisible(false) s.panelGroup.SetVisible(false)
s.setLayout()
s.onCloseCb() s.onCloseCb()
} }

View File

@ -70,6 +70,11 @@ const (
whiteAlpha100 = 0xffffffff whiteAlpha100 = 0xffffffff
) )
const (
addStatsButtonX, addStatsButtonY = 206, 561
addSkillButtonX, addSkillButtonY = 563, 561
)
// HUD represents the always visible user interface of the game // HUD represents the always visible user interface of the game
type HUD struct { type HUD struct {
actionableRegions []actionableRegion actionableRegions []actionableRegion
@ -103,7 +108,11 @@ type HUD struct {
widgetLeftSkill *d2ui.CustomWidget widgetLeftSkill *d2ui.CustomWidget
widgetRightSkill *d2ui.CustomWidget widgetRightSkill *d2ui.CustomWidget
panelBackground *d2ui.CustomWidget panelBackground *d2ui.CustomWidget
addStatsButton *d2ui.Button
addSkillButton *d2ui.Button
panelGroup *d2ui.WidgetGroup panelGroup *d2ui.WidgetGroup
gameControls *GameControls
*d2util.Logger *d2util.Logger
} }
@ -116,6 +125,7 @@ func NewHUD(
actionableRegions []actionableRegion, actionableRegions []actionableRegion,
mapEngine *d2mapengine.MapEngine, mapEngine *d2mapengine.MapEngine,
l d2util.LogLevel, l d2util.LogLevel,
gameControls *GameControls,
mapRenderer *d2maprenderer.MapRenderer, mapRenderer *d2maprenderer.MapRenderer,
) *HUD { ) *HUD {
nameLabel := ui.NewLabel(d2resource.Font16, d2resource.PaletteStatic) nameLabel := ui.NewLabel(d2resource.Font16, d2resource.PaletteStatic)
@ -149,6 +159,7 @@ func NewHUD(
zoneChangeText: zoneLabel, zoneChangeText: zoneLabel,
healthGlobe: healthGlobe, healthGlobe: healthGlobe,
manaGlobe: manaGlobe, manaGlobe: manaGlobe,
gameControls: gameControls,
} }
hud.Logger = d2util.NewLogger() hud.Logger = d2util.NewLogger()
@ -177,6 +188,16 @@ func (h *HUD) Load() {
h.loadCustomWidgets() h.loadCustomWidgets()
h.loadUIButtons() h.loadUIButtons()
h.addStatsButton = h.uiManager.NewButton(d2ui.ButtonTypeAddSkill, "")
h.addStatsButton.SetPosition(addStatsButtonX, addStatsButtonY)
h.addStatsButton.SetVisible(false)
h.panelGroup.AddWidget(h.addStatsButton)
h.addSkillButton = h.uiManager.NewButton(d2ui.ButtonTypeAddSkill, "")
h.addSkillButton.SetPosition(addSkillButtonX, addSkillButtonY)
h.addSkillButton.SetVisible(false)
h.panelGroup.AddWidget(h.addSkillButton)
h.panelGroup.SetVisible(true) h.panelGroup.SetVisible(true)
} }

View File

@ -3,6 +3,7 @@ package d2player
import ( import (
"errors" "errors"
"fmt" "fmt"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -56,6 +57,10 @@ const (
frameSelectedTab3Full = 13 frameSelectedTab3Full = 13
) )
const (
remainingPointsLabelX, remainingPointsLabelY = 677, 128
)
const ( const (
skillTreePanelX = 401 skillTreePanelX = 401
skillTreePanelY = 64 skillTreePanelY = 64
@ -87,6 +92,7 @@ type skillTreeHeroTypeResources struct {
func newSkillTree( func newSkillTree(
skills map[int]*d2hero.HeroSkill, skills map[int]*d2hero.HeroSkill,
heroClass d2enum.Hero, heroClass d2enum.Hero,
hero *d2hero.HeroStatsState,
asset *d2asset.AssetManager, asset *d2asset.AssetManager,
l d2util.LogLevel, l d2util.LogLevel,
ui *d2ui.UIManager, ui *d2ui.UIManager,
@ -98,6 +104,7 @@ func newSkillTree(
uiManager: ui, uiManager: ui,
originX: skillTreePanelX, originX: skillTreePanelX,
originY: skillTreePanelY, originY: skillTreePanelY,
stats: hero,
tab: [numTabs]*skillTreeTab{ tab: [numTabs]*skillTreeTab{
{}, {},
{}, {},
@ -124,6 +131,7 @@ type skillTree struct {
availSPLabel *d2ui.Label availSPLabel *d2ui.Label
closeButton *d2ui.Button closeButton *d2ui.Button
tab [numTabs]*skillTreeTab tab [numTabs]*skillTreeTab
remainingPoints *d2ui.Label
isOpen bool isOpen bool
originX int originX int
originY int originY int
@ -132,6 +140,7 @@ type skillTree struct {
panelGroup *d2ui.WidgetGroup panelGroup *d2ui.WidgetGroup
iconGroup *d2ui.WidgetGroup iconGroup *d2ui.WidgetGroup
panel *d2ui.CustomWidget panel *d2ui.CustomWidget
stats *d2hero.HeroStatsState
*d2util.Logger *d2util.Logger
l d2util.LogLevel l d2util.LogLevel
@ -152,6 +161,12 @@ func (s *skillTree) load() {
s.closeButton.OnActivated(func() { s.Close() }) s.closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(s.closeButton) s.panelGroup.AddWidget(s.closeButton)
s.remainingPoints = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
s.remainingPoints.SetPosition(remainingPointsLabelX, remainingPointsLabelY)
s.remainingPoints.Alignment = d2ui.HorizontalAlignCenter
s.remainingPoints.SetText(strconv.Itoa(s.stats.SkillPoints))
s.panelGroup.AddWidget(s.remainingPoints)
if err := s.setHeroTypeResourcePath(); err != nil { if err := s.setHeroTypeResourcePath(); err != nil {
s.Error(err.Error()) s.Error(err.Error())
} }

BIN
docs/game_panels.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB