1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-12-24 19:18:12 -05: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
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.
@ -128,6 +129,8 @@ which will be updated over time with new requirements.
![Inventory Window](docs/Inventory.png)
![Game Panels](docs/game_panels.png)
## Additional Credits
- Diablo2 Logo

View File

@ -243,16 +243,18 @@ const (
MinipanelSmall = "/data/global/ui/PANEL/minipanel_s.dc6"
MinipanelButton = "/data/global/ui/PANEL/minipanelbtn.DC6"
Frame = "/data/global/ui/PANEL/800borderframe.dc6"
InventoryCharacterPanel = "/data/global/ui/PANEL/invchar6.DC6"
InventoryWeaponsTab = "/data/global/ui/PANEL/invchar6Tab.DC6"
SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6"
SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6"
SkillsPanelDruid = "/data/global/ui/SPELLS/skltree_d_back.DC6"
SkillsPanelAssassin = "/data/global/ui/SPELLS/skltree_i_back.DC6"
SkillsPanelNecromancer = "/data/global/ui/SPELLS/skltree_n_back.DC6"
SkillsPanelPaladin = "/data/global/ui/SPELLS/skltree_p_back.DC6"
SkillsPanelSorcerer = "/data/global/ui/SPELLS/skltree_s_back.DC6"
Frame = "/data/global/ui/PANEL/800borderframe.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"
SkillsPanelAmazon = "/data/global/ui/SPELLS/skltree_a_back.DC6"
SkillsPanelBarbarian = "/data/global/ui/SPELLS/skltree_b_back.DC6"
SkillsPanelDruid = "/data/global/ui/SPELLS/skltree_d_back.DC6"
SkillsPanelAssassin = "/data/global/ui/SPELLS/skltree_i_back.DC6"
SkillsPanelNecromancer = "/data/global/ui/SPELLS/skltree_n_back.DC6"
SkillsPanelPaladin = "/data/global/ui/SPELLS/skltree_p_back.DC6"
SkillsPanelSorcerer = "/data/global/ui/SPELLS/skltree_s_back.DC6"
GenericSkills = "/data/global/ui/SPELLS/Skillicon.DC6"
AmazonSkills = "/data/global/ui/SPELLS/AmSkillicon.DC6"

View File

@ -10,28 +10,23 @@ type HeroStatsState struct {
Level int `json:"level"`
Experience int `json:"experience"`
Vitality int `json:"vitality"`
Energy int `json:"energy"`
Strength int `json:"strength"`
Energy int `json:"energy"`
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"`
MaxHealth int `json:"maxHealth"`
Mana int `json:"mana"`
MaxMana int `json:"maxMana"`
FireResistance int `json:"fireResistance"`
ColdResistance int `json:"coldResistance"`
LightningResistance int `json:"lightningResistance"`
PoisonResistance int `json:"poisonResistance"`
Health int `json:"health"`
MaxHealth int `json:"maxHealth"`
Mana int `json:"mana"`
MaxMana int `json:"maxMana"`
Stamina float64 `json:"-"` // only MaxStamina is saved, Stamina gets reset on entering world
MaxStamina int `json:"maxStamina"`
// 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:"-"`
}
// CreateHeroStatsState generates a running state from a hero stats.
@ -44,6 +39,8 @@ func (f *HeroStateFactory) CreateHeroStatsState(heroClass d2enum.Hero, classStat
Dexterity: classStats.InitDex,
Vitality: classStats.InitVit,
Energy: classStats.InitEne,
StatsPoints: 0,
SkillPoints: 0,
MaxHealth: classStats.InitVit * classStats.LifePerVit,
MaxMana: classStats.InitEne * classStats.ManaPerEne,

View File

@ -55,6 +55,7 @@ const (
ButtonTypeSquelchChat ButtonType = 35
ButtonTypeTabBlank ButtonType = 36
ButtonTypeBlankQuestBtn ButtonType = 37
ButtonTypeAddSkill ButtonType = 38
ButtonNoFixedWidth int = -1
ButtonNoFixedHeight int = -1
@ -199,6 +200,10 @@ const (
buttonGoldCoinSegmentsY = 1
buttonGoldCoinDisabledFrame = -1
buttonAddSkillSegmentsX = 1
buttonAddSkillSegmentsY = 1
buttonAddSkillDisabledFrame = 2
pressedButtonOffset = 2
)
@ -746,6 +751,20 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
FixedHeight: ButtonNoFixedHeight,
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
}
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)
@ -224,13 +224,9 @@ func NewGameControls(
}
helpOverlay := NewHelpOverlay(asset, ui, l, keyMap)
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, mapRenderer)
const blackAlpha50percent = 0x0000007f
hoverLabel := hud.nameLabel
hoverLabel.SetBackgroundColor(d2util.Color(blackAlpha50percent))
gc := &GameControls{
asset: asset,
ui: ui,
@ -246,7 +242,6 @@ func NewGameControls(
questLog: questLog,
HelpOverlay: helpOverlay,
keyMap: keyMap,
hud: hud,
bottomMenuRect: &d2geom.Rectangle{
Left: menuBottomRectX,
Top: menuBottomRectY,
@ -271,6 +266,12 @@ func NewGameControls(
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.questLog.SetOnCloseCb(gc.onCloseQuestLog)
gc.inventory.SetOnCloseCb(gc.onCloseInventory)
@ -713,6 +714,9 @@ func (g *GameControls) Load() {
g.questLog.Load()
g.HelpOverlay.Load()
g.loadAddButtons()
g.setAddButtons()
miniPanelActions := &miniPanelActions{
characterToggle: g.toggleHeroStatsPanel,
inventoryToggle: g.toggleInventoryPanel,
@ -733,6 +737,10 @@ func (g *GameControls) Advance(elapsed float64) error {
return err
}
if g.heroStatsPanel.IsOpen() || g.skilltree.IsOpen() {
g.setAddButtons()
}
return nil
}
@ -1099,3 +1107,13 @@ func (g *GameControls) bindTerminalCommands(term d2interface.Terminal) error {
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/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
@ -55,6 +56,15 @@ const (
const (
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
@ -113,15 +123,17 @@ func NewHeroStatsPanel(asset *d2asset.AssetManager,
// HeroStatsPanel represents the hero status panel
type HeroStatsPanel struct {
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
panel *d2ui.Sprite
heroState *d2hero.HeroStatsState
heroName string
heroClass d2enum.Hero
labels *StatsPanelLabels
onCloseCb func()
panelGroup *d2ui.WidgetGroup
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
panel *d2ui.Sprite
heroState *d2hero.HeroStatsState
heroName string
heroClass d2enum.Hero
labels *StatsPanelLabels
onCloseCb func()
panelGroup *d2ui.WidgetGroup
newStatPoints *d2ui.WidgetGroup
remainingPoints *d2ui.Label
originX int
originY int
@ -135,6 +147,7 @@ func (s *HeroStatsPanel) Load() {
var err error
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
s.newStatPoints = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
s.panelGroup.AddWidget(frame)
@ -154,10 +167,91 @@ func (s *HeroStatsPanel) Load() {
closeButton.OnActivated(func() { s.Close() })
s.panelGroup.AddWidget(closeButton)
s.loadNewStatPoints()
s.setLayout()
s.initStatValueLabels()
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
func (s *HeroStatsPanel) IsOpen() bool {
return s.isOpen
@ -176,12 +270,14 @@ func (s *HeroStatsPanel) Toggle() {
func (s *HeroStatsPanel) Open() {
s.isOpen = true
s.panelGroup.SetVisible(true)
s.setLayout()
}
// Close closed the hero status panel
func (s *HeroStatsPanel) Close() {
s.isOpen = false
s.panelGroup.SetVisible(false)
s.setLayout()
s.onCloseCb()
}

View File

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

View File

@ -3,6 +3,7 @@ package d2player
import (
"errors"
"fmt"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -56,6 +57,10 @@ const (
frameSelectedTab3Full = 13
)
const (
remainingPointsLabelX, remainingPointsLabelY = 677, 128
)
const (
skillTreePanelX = 401
skillTreePanelY = 64
@ -87,6 +92,7 @@ type skillTreeHeroTypeResources struct {
func newSkillTree(
skills map[int]*d2hero.HeroSkill,
heroClass d2enum.Hero,
hero *d2hero.HeroStatsState,
asset *d2asset.AssetManager,
l d2util.LogLevel,
ui *d2ui.UIManager,
@ -98,6 +104,7 @@ func newSkillTree(
uiManager: ui,
originX: skillTreePanelX,
originY: skillTreePanelY,
stats: hero,
tab: [numTabs]*skillTreeTab{
{},
{},
@ -114,24 +121,26 @@ func newSkillTree(
}
type skillTree struct {
resources *skillTreeHeroTypeResources
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
skills map[int]*d2hero.HeroSkill
skillIcons []*skillIcon
heroClass d2enum.Hero
frame *d2ui.UIFrame
availSPLabel *d2ui.Label
closeButton *d2ui.Button
tab [numTabs]*skillTreeTab
isOpen bool
originX int
originY int
selectedTab int
onCloseCb func()
panelGroup *d2ui.WidgetGroup
iconGroup *d2ui.WidgetGroup
panel *d2ui.CustomWidget
resources *skillTreeHeroTypeResources
asset *d2asset.AssetManager
uiManager *d2ui.UIManager
skills map[int]*d2hero.HeroSkill
skillIcons []*skillIcon
heroClass d2enum.Hero
frame *d2ui.UIFrame
availSPLabel *d2ui.Label
closeButton *d2ui.Button
tab [numTabs]*skillTreeTab
remainingPoints *d2ui.Label
isOpen bool
originX int
originY int
selectedTab int
onCloseCb func()
panelGroup *d2ui.WidgetGroup
iconGroup *d2ui.WidgetGroup
panel *d2ui.CustomWidget
stats *d2hero.HeroStatsState
*d2util.Logger
l d2util.LogLevel
@ -152,6 +161,12 @@ func (s *skillTree) load() {
s.closeButton.OnActivated(func() { s.Close() })
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 {
s.Error(err.Error())
}

BIN
docs/game_panels.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB