diff --git a/data/styles/30-statsbar.otui b/data/styles/30-statsbar.otui index ce589bf468..c613d97df0 100644 --- a/data/styles/30-statsbar.otui +++ b/data/styles/30-statsbar.otui @@ -363,7 +363,7 @@ TopStatsBarLargeOnTop < UIWidget anchors.top: icons.bottom margin-top: 6 margin-left: 12 - margin-right: 12 + margin-right: 18 height: 0 TopStatsBarParallelOnTop < UIWidget @@ -402,7 +402,7 @@ TopStatsBarParallelOnTop < UIWidget anchors.right: parent.right anchors.top: mana.bottom margin-left: 12 - margin-right: 12 + margin-right: 18 height: 0 Panel @@ -453,7 +453,7 @@ TopStatsBarDefaultOnTop < UIWidget anchors.right: parent.right anchors.top: mana.bottom margin-left: 12 - margin-right: 12 + margin-right: 18 height: 0 Panel @@ -514,7 +514,7 @@ TopStatsBarCompactOnTop < UIWidget anchors.top: icons.bottom margin-top: 6 margin-left: 12 - margin-right: 12 + margin-right: 18 height: 0 TopStatsBar < UIWidget @@ -541,3 +541,547 @@ TopStatsBar < UIWidget anchors.fill: parent visible: false phantom: true + + TopStatsBarLargeOnBottom + id: largeOnBottom + anchors.fill: parent + visible: false + phantom: true + + TopStatsBarParallelOnBottom + id: parallelOnBottom + anchors.fill: parent + visible: false + phantom: true + + TopStatsBarDefaultOnBottom + id: defaultOnBottom + anchors.fill: parent + visible: false + phantom: true + + TopStatsBarCompactOnBottom + id: compactOnBottom + anchors.fill: parent + visible: false + phantom: true + +StatsBarDarkBackground < UIWidget + UIWidget + anchors.fill: parent + image-source: /images/ui/containerslot + image-border: 3 + +StatsHorizontalBarGrade < UIWidget + UIWidget + id: grade_border_1 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + background-color: #ffffffff + height: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_2 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + background-color: #ffffffff + height: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_3 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + background-color: #ffffffff + width: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_4 + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.top: parent.top + background-color: #ffffffff + width: 1 + visible: false + phantom: false + + UIWidget + id: grade_left_1 + anchors.left: parent.left + anchors.top: parent.top + image-source: /images/bars/marker_top + size: 7 11 + visible: false + phantom: false + + UIWidget + id: grade_left_2 + anchors.left: parent.left + anchors.top: parent.top + image-source: /images/bars/marker_top + size: 7 11 + visible: false + phantom: false + + UIWidget + id: grade_right_1 + anchors.right: parent.right + anchors.top: parent.top + image-source: /images/bars/marker_top + size: 7 11 + visible: false + phantom: false + + UIWidget + id: grade_right_2 + anchors.right: parent.right + anchors.top: parent.top + image-source: /images/bars/marker_top + size: 7 11 + visible: false + phantom: false + +StatsVerticalLeftBarGrade < UIWidget + UIWidget + id: grade_border_1 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + background-color: #ffffffff + height: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_2 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + background-color: #ffffffff + height: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_3 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + background-color: #ffffffff + width: 1 + visible: false + phantom: false + + UIWidget + id: grade_border_4 + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.top: parent.top + background-color: #ffffffff + width: 1 + visible: false + phantom: false + + UIWidget + id: grade_top_1 + anchors.left: parent.left + anchors.top: parent.top + image-source: /images/bars/marker_left + size: 11 7 + visible: false + phantom: false + + UIWidget + id: grade_top_2 + anchors.left: parent.left + anchors.top: parent.top + image-source: /images/bars/marker_left + size: 11 7 + visible: false + phantom: false + + UIWidget + id: grade_bottom_1 + anchors.left: parent.left + anchors.bottom: parent.bottom + image-source: /images/bars/marker_left + size: 11 7 + visible: false + phantom: false + + UIWidget + id: grade_bottom_2 + anchors.left: parent.left + anchors.bottom: parent.bottom + image-source: /images/bars/marker_left + size: 11 7 + visible: false + phantom: false + +StatsBarUp < UIStatsBar + StatsBarDarkBackground + anchors.fill: parent + phantom: true + + UIWidget + id: bar + width: 1 + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parente.bottom + margin: 1 + image-repeated: true + + StatsHorizontalBarGrade + id: horizontalGrade + anchors.fill: parent + visible: false + + Label + id: text + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text-align: center + visible: false + !text: '9999999999/9999999999' + +StatsBarBottomWithShrink < UIWidget + UIWidget + anchors.fill: parent + image-source: /images/ui/background + image-repeated: true + + UIWidget + anchors.right: rightBottomIncreaseSidePanels.left + anchors.left: leftBottomIncreaseSidePanels.right + anchors.top: parent.top + height: 2 + background-color: white + opacity: 0.35 + + UIWidget + anchors.right: rightBottomIncreaseSidePanels.left + anchors.top: parent.top + anchors.bottom: rightBottomDecreaseSidePanels.bottom + margin-bottom: -2 + margin-top: 2 + width: 2 + background-color: black + opacity: 0 + + UIWidget + anchors.right: parent.right + anchors.left: prev.left + anchors.top: rightBottomDecreaseSidePanels.bottom + height: 2 + background-color: white + opacity: 0.35 + + UIWidget + anchors.right: parent.right + anchors.top: prev.bottom + anchors.bottom: parent.bottom + width: 2 + background-color: black + opacity: 0 + + UIWidget + anchors.right: parent.right + anchors.left: parent.left + anchors.bottom: parent.bottom + margin-left: 2 + margin-right: 2 + height: 2 + background-color: black + opacity: 0 + + UIWidget + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: leftBottomDecreaseSidePanels.bottom + width: 1 + background-color: white + opacity: 0 + + UIWidget + anchors.left: parent.left + anchors.top: leftBottomDecreaseSidePanels.bottom + anchors.right: leftBottomDecreaseSidePanels.right + margin-left: 1 + height: 1 + background-color: white + opacity: 0 + + UIWidget + anchors.left: leftBottomDecreaseSidePanels.right + anchors.bottom: leftBottomDecreaseSidePanels.bottom + anchors.top: parent.top + margin-top: 2 + width: 2 + background-color: black + opacity: 0 + + UIWidget + id: leftBottomIncreaseSidePanels + anchors.left: parent.left + anchors.top: parent.top + size: 0 0 + + UIWidget + id: leftBottomDecreaseSidePanels + anchors.left: parent.left + anchors.top: leftBottomIncreaseSidePanels.bottom + size: 0 0 + + UIWidget + id: rightBottomIncreaseSidePanels + anchors.right: parent.right + anchors.top: parent.top + size: 0 0 + + UIWidget + id: rightDecreaseSidePanels + anchors.right: parent.right + anchors.top: rightBottomIncreaseSidePanels.bottom + size: 0 0 + + +BottomStatsSkillElement < UIWidget + height: 20 + + Label + id: levelBottom + !text: '99999' + color: #c0c0c0ff + text-align: right + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + margin-left: 10 + + UIWidget + id: icon + size: 9 9 + anchors.verticalCenter: levelBottom.verticalCenter + anchors.left: levelBottom.right + margin-left: 7 + + StatsBarUp + id: bar + anchors.verticalCenter: levelBottom.verticalCenter + anchors.left: icon.right + anchors.right: parent.right + !statsbar-size: 'tiny' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 5 + height: 7 + +TopStatsBarLargeOnBottom < UIWidget + StatsBarBottomWithShrink + anchors.fill: parent + + Panel + id: icons + image-border: 3 + image-source: /images/ui/containerslot + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + margin-top: 7 + margin-bottom: 3 + size: 75 27 + layout: + type: horizontalBox + + StatsBarUp + id: health + anchors.top: icons.top + anchors.left: parent.left + anchors.right: icons.left + !statsbar-type: 'health' + !statsbar-size: 'large' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + margin-top: 0 + margin-bottom: 6 + height: 27 + + StatsBarUp + id: mana + anchors.top: icons.top + anchors.right: parent.right + anchors.left: icons.right + !statsbar-type: 'mana' + !statsbar-size: 'large' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + margin-top: 0 + height: 27 + + Panel + id: skills + anchors.left: parent.left + anchors.right: parent.right + anchors.top: icons.bottom + margin-top: 8 + margin-right: 6 + height: 0 + +TopStatsBarParallelOnBottom < UIWidget + StatsBarBottomWithShrink + anchors.fill: parent + + StatsBarUp + id: health + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + !statsbar-type: 'health' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + margin-top: 8 + height: 14 + + StatsBarUp + id: mana + anchors.top: health.bottom + anchors.left: health.left + anchors.right: health.right + !statsbar-type: 'mana' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-top: 8 + height: 14 + + Panel + id: skills + anchors.left: parent.left + anchors.right: parent.right + anchors.top: mana.bottom + margin-right: 6 + height: 0 + + Panel + id: icons + image-border: 3 + image-source: /images/ui/containerslot + anchors.top: skills.bottom + anchors.horizontalCenter: parent.horizontalCenter + size: 103 14 + layout: + type: horizontalBox + +TopStatsBarDefaultOnBottom < UIWidget + StatsBarBottomWithShrink + anchors.fill: parent + + StatsBarUp + id: health + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.horizontalCenter + !statsbar-type: 'health' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + margin-top: 8 + height: 14 + + StatsBarUp + id: mana + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.horizontalCenter + !statsbar-type: 'mana' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + margin-top: 8 + height: 14 + + Panel + id: skills + anchors.left: parent.left + anchors.right: parent.right + anchors.top: mana.bottom + height: 0 + + Panel + id: icons + image-border: 3 + image-source: /images/ui/containerslot + anchors.top: skills.bottom + anchors.horizontalCenter: parent.horizontalCenter + size: 103 14 + layout: + type: horizontalBox + +TopStatsBarCompactOnBottom < UIWidget + StatsBarBottomWithShrink + anchors.fill: parent + + Panel + id: icons + image-border: 3 + image-source: /images/ui/containerslot + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + achors.bottom: paren.bottom + margin-top: 8 + size: 53 14 + layout: + type: horizontalBox + + StatsBarUp + id: health + anchors.top: icons.top + anchors.left: parent.left + anchors.right: icons.left + !statsbar-type: 'health' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + height: 14 + + StatsBarUp + id: mana + anchors.top: icons.top + anchors.right: parent.right + anchors.left: icons.right + !statsbar-type: 'mana' + !statsbar-size: 'small' + !statsbar-orientation: 'horizontal' + statsbar-text: true + margin-left: 7 + margin-right: 7 + height: 14 + + Panel + id: skills + anchors.left: parent.left + anchors.right: parent.right + anchors.top: icons.bottom + margin-top: 6 + margin-right: 6 + height: 0 diff --git a/modules/client_options/data_options.lua b/modules/client_options/data_options.lua index 9e4825d094..fadff65bd3 100644 --- a/modules/client_options/data_options.lua +++ b/modules/client_options/data_options.lua @@ -358,4 +358,4 @@ return { modules.game_healthcircle.setCircleOpacity(bar:recursiveGetChildById('valueBar'):getValue() / 100) end } -} +} \ No newline at end of file diff --git a/modules/client_options/general.otui b/modules/client_options/general.otui index 0c600986b4..16057d90d4 100644 --- a/modules/client_options/general.otui +++ b/modules/client_options/general.otui @@ -175,4 +175,4 @@ Panel margin-left: 10 anchors.verticalCenter: prev.verticalCenter anchors.left: prev.right - mouse-scroll: false + mouse-scroll: false \ No newline at end of file diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index d3eb3ab644..3d92211f0e 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -247,6 +247,7 @@ function init() -- toggle WASD consoleToggleChat = consolePanel:getChildById('toggleChat') + load() if g_game.isOnline() then diff --git a/modules/game_healthcircle/game_healthcircle.lua b/modules/game_healthcircle/game_healthcircle.lua index e560550b74..4bea172863 100644 --- a/modules/game_healthcircle/game_healthcircle.lua +++ b/modules/game_healthcircle/game_healthcircle.lua @@ -505,7 +505,8 @@ manaCheckBox = nil experienceCheckBox = nil skillCheckBox = nil chooseSkillComboBox = nil -chooseTopBarDimension = nil +chooseStatsBarDimension = nil +chooseStatsBarPlacement = nil distFromCenScrollbar = nil opacityScrollbar = nil @@ -520,7 +521,8 @@ function addToOptionsModule() experienceCheckBox = optionPanel:recursiveGetChildById('experienceCheckBox') skillCheckBox = optionPanel:recursiveGetChildById('skillCheckBox') chooseSkillComboBox = optionPanel:recursiveGetChildById('chooseSkillComboBox') - chooseTopBarDimension = optionPanel:recursiveGetChildById('chooseTopBarDimension') + chooseStatsBarDimension = optionPanel:recursiveGetChildById('chooseStatsBarDimension') + chooseStatsBarPlacement = optionPanel:recursiveGetChildById('chooseStatsBarPlacement') distFromCenScrollbar = optionPanel:recursiveGetChildById('distFromCenScrollbar') opacityScrollbar = optionPanel:recursiveGetChildById('opacityScrollbar') @@ -534,11 +536,19 @@ function addToOptionsModule() chooseSkillComboBox:addOption('Shielding', 'shielding') chooseSkillComboBox:addOption('Fishing', 'fishing') - chooseTopBarDimension:addOption(tr('Compact'), 'compact') - chooseTopBarDimension:addOption(tr('Default'), 'default') - chooseTopBarDimension:addOption(tr('Hide'), 'hide') - chooseTopBarDimension:addOption(tr('Large'), 'large') - chooseTopBarDimension:addOption(tr('Parallel'), 'parallel') + chooseStatsBarPlacement:addOption(tr('Top'), 'top') + chooseStatsBarPlacement:addOption(tr('Bottom'), 'bottom') + + chooseStatsBarDimension:addOption(tr('Hide'), 'hide') + chooseStatsBarDimension:addOption(tr('Compact'), 'compact') + chooseStatsBarDimension:addOption(tr('Default'), 'default') + chooseStatsBarDimension:addOption(tr('Large'), 'large') + chooseStatsBarDimension:addOption(tr('Parallel'), 'parallel') + + statsBarMenuLoaded = true + + chooseStatsBarDimension:setCurrentOptionByData(g_settings.getString('statsbar_dimension'), true) + chooseStatsBarPlacement:setCurrentOptionByData(g_settings.getString('statsbar_placement'), true) -- Set values healthCheckBox:setChecked(isHealthCircle) @@ -555,6 +565,12 @@ function addToOptionsModule() opacityScrollbar:setValue(opacityCircle * 100) end +function updateStatsBar() + if statsBarMenuLoaded then + modules.game_interface.updateStatsBar(chooseStatsBarDimension:getCurrentOption().data, chooseStatsBarPlacement:getCurrentOption().data) + end +end + function setPlayerValues() local skillType = skillTypes[g_game.getCharacterName()] if not skillType then @@ -563,8 +579,9 @@ function setPlayerValues() chooseSkillComboBox:setCurrentOptionByData(skillType, true) end -function setTopBarOption(data, placement) - chooseTopBarDimension:setCurrentOptionByData(data, true) +function setStatsBarOption(dimension, placement) + chooseStatsBarDimension:setCurrentOptionByData(dimension, true) + chooseStatsBarPlacement:setCurrentOptionByData(placement, true) end function destroyOptionsModule() @@ -575,7 +592,8 @@ function destroyOptionsModule() chooseSkillComboBox = nil distFromCenScrollbar = nil opacityScrollbar = nil - chooseTopBarDimension = nil + chooseStatsBarDimension = nil + chooseStatsBarPlacement = nil modules.client_options.removeTab('HP/MP Circle') optionPanel = nil diff --git a/modules/game_healthcircle/option_healthcircle.otui b/modules/game_healthcircle/option_healthcircle.otui index bf6c0ace61..d4022c562b 100644 --- a/modules/game_healthcircle/option_healthcircle.otui +++ b/modules/game_healthcircle/option_healthcircle.otui @@ -139,17 +139,26 @@ Panel height: 32 Label - !text: tr('Top Bar Style:') + !text: tr('Bar Style:') anchors.left: parent.left margin-left: 18 color: #c0c0c0ff anchors.verticalCenter: parent.verticalCenter QtComboBox - id: chooseTopBarDimension + id: chooseStatsBarPlacement width: 120 margin-left: 10 anchors.verticalCenter: prev.verticalCenter anchors.left: prev.right mouse-scroll: false - @onTextChange: modules.game_interface.setStatsBarOption(self:getCurrentOption().data, 'top') + @onTextChange: modules.game_healthcircle.updateStatsBar() + + QtComboBox + id: chooseStatsBarDimension + width: 120 + margin-left: 10 + anchors.verticalCenter: prev.verticalCenter + anchors.left: prev.right + mouse-scroll: false + @onTextChange: modules.game_healthcircle.updateStatsBar() diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index ce0e61ce09..96eb03e639 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -11,6 +11,7 @@ gameSelectedPanel = nil panelsList = {} panelsRadioGroup = nil gameTopPanel = nil +gameBottomStatsBarPanel = nil gameBottomPanel = nil showTopMenuButton = nil logoutButton = nil @@ -78,6 +79,7 @@ function init() gameLeftPanel = gameRootPanel:getChildById('gameLeftPanel') gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel') gameTopPanel = gameRootPanel:getChildById('gameTopPanel') + gameBottomStatsBarPanel = gameRootPanel:getChildById('gameBottomStatsBarPanel') leftIncreaseSidePanels = gameRootPanel:getChildById('leftIncreaseSidePanels') leftDecreaseSidePanels = gameRootPanel:getChildById('leftDecreaseSidePanels') @@ -1171,6 +1173,10 @@ function getGameTopStatsBar() return gameTopPanel end +function getGameBottomStatsBar() + return gameBottomStatsBarPanel +end + function getGameMapPanel() return gameMapPanel end @@ -1280,8 +1286,9 @@ function limitZoom() end -function setStatsBarOption(dimension, placement) - StatsBar.setStatsBarOption(dimension, placement) +function updateStatsBar(dimension, placement) + StatsBar.updateCurrentStats(dimension, placement) + StatsBar.updateStatsBarOption() end function onIncreaseLeftPanels() diff --git a/modules/game_interface/gameinterface.otui b/modules/game_interface/gameinterface.otui index 1261776733..5a2a53ddb1 100644 --- a/modules/game_interface/gameinterface.otui +++ b/modules/game_interface/gameinterface.otui @@ -45,6 +45,7 @@ UIWidget anchors.right: gameRightExtraPanel.left anchors.top: gameTopPanel.bottom anchors.bottom: gameBottomPanel.top + focusable: false Button @@ -59,7 +60,7 @@ UIWidget id: gameBottomPanel anchors.left: gameLeftExtraPanel.right anchors.right: gameRightExtraPanel.left - anchors.top: bottomSplitter.top + anchors.top: gameBottomStatsBarPanel.bottom anchors.bottom: parent.bottom GameSidePanel @@ -162,6 +163,16 @@ UIWidget anchors.right: gameRightExtraPanel.left anchors.top: parent.top focusable: false + + TopStatsBar + id: gameBottomStatsBarPanel + anchors.left: gameLeftExtraPanel.right + anchors.right: gameRightExtraPanel.left + anchors.top: bottomSplitter.bottom + margin-left: 1 + margin-right: 1 + focusable: false + Button id: leftIncreaseSidePanels anchors.left: gameLeftExtraPanel.right diff --git a/modules/game_interface/widgets/statsbar.lua b/modules/game_interface/widgets/statsbar.lua index dc409080f2..52fe855ac3 100644 --- a/modules/game_interface/widgets/statsbar.lua +++ b/modules/game_interface/widgets/statsbar.lua @@ -1,9 +1,40 @@ -local statsBar +local statsBarTop +local statsBarBottom + +local statsBars = {} +local statsBarDeepInfo = {} + +-- If you want to add more placements/dimensions, you'll need to add them here. +-- This is used in getStatsBarMenuOptions(), createStatsBarWidgets(), +-- hideAll() and destroyAllIcons() functions. +local statsBarsPlacements = { + "Top", + "Bottom" +} + +-- This is used in constructStatsBar(), getStatsBarMenuOptions(), +-- reloadCurrentTab(), createStatsBarWidgets(), +-- hideAll() and destroyALlIcons functions. +local statsBarsDimensions = { + Large = { + height = 35 + }, + Default = { + height = 35 + }, + Parallel = { + height = 35 + }, + Compact = { + height = 20 + } +} + local firstCall = true local currentStats = { - dimension = 'hide', - placement = 'hide' + dimension = "hide", + placement = "hide" } local skillsLineHeight = 20 @@ -20,8 +51,11 @@ local skillsTuples = { } StatsBar = {} + + local function createBlankIcon() - local statsBarConfigs = {statsBar.largeOnTop, statsBar.parallelOnTop, statsBar.defaultOnTop, statsBar.compactOnTop} + local statsBarConfigs = getConfigurations() + for _, statsBarConfig in ipairs(statsBarConfigs) do local icon = g_ui.createWidget('ConditionWidget', statsBarConfig.icons) icon:setImageSource('/images/ui/blank') @@ -33,7 +67,25 @@ local function createBlankIcon() end end +function getConfigurations() + -- This method will return all the stats bar configurations. + local configs = {} + for _, statsBar in pairs(statsBars) do + for _, placement in ipairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local dimensionOnPlacement = tostring(dimension):lower() .. "On" .. placement + local key = "statsBar" .. placement:gsub("^%l", string.upper) + if statsBar[key] then + table.insert(configs, statsBar[key][dimensionOnPlacement]) + end + end + end + end + return configs +end + local function reloadSkillsTab(skills, parent) + -- This method might need some refactoring if you want to add side stats bars. local player = g_game.getLocalPlayer() if not player then return @@ -47,7 +99,13 @@ local function reloadSkillsTab(skills, parent) end end + local statsBar = StatsBar.getCurrentStatsBar() + if not statsBar then + return + end + statsBar:setHeight(statsBar:getHeight() - skills:getHeight()) + parent:setHeight(parent:getHeight() - (40 + skills:getHeight())) skills:setHeight(0) skills:destroyChildren() @@ -109,31 +167,76 @@ local function reloadSkillsTab(skills, parent) end - skills:setHeight(lines * skillsLineHeight) - if parent:getId() == 'largeOnTop' then - skills:setHeight(skills:getHeight() + 5) - elseif lines == 0 then - skills:setHeight(skills:getHeight() + 5) - end + skills:setHeight((lines * skillsLineHeight) + 5) parent:setHeight(40 + skills:getHeight()) statsBar:setHeight(statsBar:getHeight() + skills:getHeight()) end -function StatsBar.getCurrentStatsBar() +function StatsBar.getAllStatsBarWithPosition() + -- This method will return all the stats bars based on their placement and dimension. + -- i.e statsBarTop.largeOnTop, statsBarTop.parallelOnTop, statsBarTop.defaultOnTop, statsBarTop.compactOnTop [..] + local statsBarsWithPosition = {} + for _, statsBar in pairs(statsBars) do + for _, placement in ipairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local dimensionOnPlacement = tostring(dimension):lower() .. "On" .. placement + if statsBar[dimensionOnPlacement] then + statsBarsWithPosition[#statsBarsWithPosition+1] = statsBar[dimensionOnPlacement] + end + end + end + end + + return statsBarsWithPosition +end + +function StatsBar.getCurrentStatsBarWithPosition() + -- This method will return the statsbar based on its placement and dimension. + -- i.e "largeOnTop" will return statsBarTop.largeOnTop. + -- It's made this way so we can call the current stats bar without having to use a switch statement. + -- And if it's necessary to add more stats bars like "largeOnLeft" it will be easier to add them + -- Without changing this code. if currentStats.dimension == 'hide' and currentStats.placement == 'hide' then return nil end + -- -- Get full position as a single string. + -- -- i.e. largeOnTop // parallelOnBottom + local placement = currentStats.placement:gsub("^%l", string.upper) + local fullPosition = currentStats.dimension .. "On" .. placement + local statsBar = StatsBar.getCurrentStatsBar() + if not statsBar then + return nil + end - if currentStats.placement == 'top' then - if currentStats.dimension == 'large' then - return statsBar.largeOnTop - elseif currentStats.dimension == 'parallel' then - return statsBar.parallelOnTop - elseif currentStats.dimension == 'default' then - return statsBar.defaultOnTop - elseif currentStats.dimension == 'compact' then - return statsBar.compactOnTop - end + if statsBar[fullPosition] then + -- Return the stats bar based on the full position. + -- i.e. statsBarTop.largeOnTop + return statsBar[fullPosition] + else + print("No stats bar with position found for:", statsBar) + end + + return nil +end + +function StatsBar.getCurrentStatsBar() + -- This method will return the statsbar based on its placement. + -- i.e statsBarTop // statsBarBottom + if currentStats.dimension == 'hide' and currentStats.placement == 'hide' then + return nil + end + -- -- Get full placement. + -- -- i.e. Top // Bottom + local placement = currentStats.placement:gsub("^%l", string.upper) + + -- -- Get the stats bar based on the placement. + -- -- i.e. statsBarTop // statsBarBottom + local statsBar = "statsBar" .. placement + + if statsBars[statsBar] then + return statsBars[statsBar] + else + print("No stats bar found for:", statsBar) end return nil @@ -145,14 +248,13 @@ function StatsBar.reloadCurrentStatsBarQuickInfo() return end - local bar = StatsBar.getCurrentStatsBar() + local bar = StatsBar.getCurrentStatsBarWithPosition() if not bar then return end bar.health:setValue(player:getHealth(), player:getMaxHealth()) bar.mana:setValue(player:getMana(), player:getMaxMana()) - end local function loadIcon(bitChanged, content, topmenu) @@ -170,15 +272,22 @@ local function loadIcon(bitChanged, content, topmenu) return icon end +local function getStatsBarsIconContent() + local iconContents = {} + local statsBars = StatsBar.getAllStatsBarWithPosition() + + for _, statsBar in ipairs(statsBars) do + iconContents[#iconContents+1] = { content = statsBar.icons, loadIconTransparent = true } + end + + iconContents[#iconContents+1] = { content = modules.game_inventory.getIconsPanelOn(), loadIconTransparent = false } + iconContents[#iconContents+1] = { content = modules.game_inventory.getIconsPanelOff(), loadIconTransparent = false } + + return iconContents +end + local function toggleIcon(bitChanged) - local contents = { - {content = statsBar.largeOnTop.icons,loadIconTransparent = true}, - {content = statsBar.parallelOnTop.icons,loadIconTransparent = true}, - {content = statsBar.defaultOnTop.icons,loadIconTransparent = true}, - {content = statsBar.compactOnTop.icons, loadIconTransparent = true}, - {content = modules.game_inventory.getIconsPanelOff()}, - {content = modules.game_inventory.getIconsPanelOn()} - } + local contents = getStatsBarsIconContent() for _, contentData in ipairs(contents) do local icon = contentData.content:getChildById(Icons[bitChanged].id) @@ -220,7 +329,7 @@ function StatsBar.reloadCurrentStatsBarDeepInfo() return end - local bar = StatsBar.getCurrentStatsBar() + local bar = StatsBar.getCurrentStatsBarWithPosition() if not bar then return end @@ -242,165 +351,57 @@ function StatsBar.reloadCurrentStatsBarDeepInfo() end end -function StatsBar.hideAll() - - statsBar.largeOnTop.skills:destroyChildren() - statsBar.largeOnTop.skills:setHeight(0) - statsBar.largeOnTop:setHeight(0) - statsBar.largeOnTop:hide() - - statsBar.parallelOnTop.skills:destroyChildren() - statsBar.parallelOnTop.skills:setHeight(0) - statsBar.parallelOnTop:setHeight(0) - statsBar.parallelOnTop:hide() - - statsBar.defaultOnTop.skills:destroyChildren() - statsBar.defaultOnTop.skills:setHeight(0) - statsBar.defaultOnTop:setHeight(0) - statsBar.defaultOnTop:hide() - - statsBar.compactOnTop.skills:destroyChildren() - statsBar.compactOnTop.skills:setHeight(0) - statsBar.compactOnTop:setHeight(0) - statsBar.compactOnTop:hide() - - statsBar:setHeight(0) - currentStats = { - dimension = 'hide', - placement = 'hide' - } - - -- modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) -end - -local function constructLargeOnTop() - statsBar:setHeight(35) - statsBar.largeOnTop:setHeight(35) - statsBar.largeOnTop:show() - - currentStats = { - dimension = 'large', - placement = 'top' - } - - statsBar.largeOnTop:show() - statsBar.largeOnTop:setPhantom(false) - statsBar.largeOnTop.health = statsBar.largeOnTop:getChildById('health') - statsBar.largeOnTop.mana = statsBar.largeOnTop:getChildById('mana') - statsBar.largeOnTop.skills = statsBar.largeOnTop:getChildById('skills') - - reloadSkillsTab(statsBar.largeOnTop.skills, statsBar.largeOnTop) - StatsBar.reloadCurrentStatsBarQuickInfo() - - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) - return true -end - -local function constructParallelOnTop() - statsBar:setHeight(55) - statsBar.parallelOnTop:setHeight(55) - statsBar.parallelOnTop:show() +function constructStatsBar(dimension, placement) + local dimensionString = dimension:gsub("^%u", string.lower) + StatsBar.updateCurrentStats(dimensionString, placement) - currentStats = { - dimension = 'parallel', - placement = 'top' - } + local dimensionOnPlacement = dimensionString:gsub("^%u", string.lower) .. "On" .. placement:gsub("^%l", string.upper) + local statsBar = statsBars["statsBar" .. placement:gsub("^%l", string.upper)] - statsBar.parallelOnTop:show() - statsBar.parallelOnTop:setPhantom(false) - statsBar.parallelOnTop.health = statsBar.parallelOnTop:getChildById('health') - statsBar.parallelOnTop.mana = statsBar.parallelOnTop:getChildById('mana') - statsBar.parallelOnTop.skills = statsBar.parallelOnTop:getChildById('skills') + if statsBar[dimensionOnPlacement] then + statsBar:setHeight(statsBarsDimensions[dimension].height) + statsBar[dimensionOnPlacement]:setHeight(statsBarsDimensions[dimension].height) + statsBar[dimensionOnPlacement]:show() + statsBar[dimensionOnPlacement]:setPhantom(false) + statsBar[dimensionOnPlacement].health = statsBar[dimensionOnPlacement]:getChildById('health') + statsBar[dimensionOnPlacement].mana = statsBar[dimensionOnPlacement]:getChildById('mana') + statsBar[dimensionOnPlacement].skills = statsBar[dimensionOnPlacement]:getChildById('skills') - reloadSkillsTab(statsBar.parallelOnTop.skills, statsBar.parallelOnTop) + reloadSkillsTab(statsBar[dimensionOnPlacement].skills, statsBar[dimensionOnPlacement]) StatsBar.reloadCurrentStatsBarQuickInfo() - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) - return true -end - -local function constructDefaultOnTop() - statsBar:setHeight(35) - statsBar.defaultOnTop:setHeight(35) - statsBar.defaultOnTop:show() - - currentStats = { - dimension = 'default', - placement = 'top' - } - - statsBar.defaultOnTop:show() - statsBar.defaultOnTop:setPhantom(false) - statsBar.defaultOnTop.health = statsBar.defaultOnTop:getChildById('health') - statsBar.defaultOnTop.mana = statsBar.defaultOnTop:getChildById('mana') - statsBar.defaultOnTop.skills = statsBar.defaultOnTop:getChildById('skills') - - reloadSkillsTab(statsBar.defaultOnTop.skills, statsBar.defaultOnTop) - StatsBar.reloadCurrentStatsBarQuickInfo() - - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) - return true + modules.game_healthcircle.setStatsBarOption() + else + print("No stats bar found for:", dimensionOnPlacement .. " on constructStatsBar()") + end end -local function constructCompactOnTop() - statsBar:setHeight(35) - statsBar.compactOnTop:setHeight(35) - statsBar.compactOnTop:show() - +function StatsBar.updateCurrentStats(dimension, placement) currentStats = { - dimension = 'compact', - placement = 'top' + dimension = dimension, + placement = placement } - - statsBar.compactOnTop:show() - statsBar.compactOnTop:setPhantom(false) - statsBar.compactOnTop.health = statsBar.compactOnTop:getChildById('health') - statsBar.compactOnTop.mana = statsBar.compactOnTop:getChildById('mana') - statsBar.compactOnTop.skills = statsBar.compactOnTop:getChildById('skills') - - reloadSkillsTab(statsBar.compactOnTop.skills, statsBar.compactOnTop) - StatsBar.reloadCurrentStatsBarQuickInfo() - - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) - return true end local function openDropMenu(mousePos) local menu = g_ui.createWidget('PopupMenu') menu:setGameMenu(true) - local current = StatsBar.getCurrentStatsBar() - if not (current) or current:getId() ~= 'compactOnTop' then - menu:addOption(tr('Switch to Compact Style'), function() - StatsBar.hideAll() - constructCompactOnTop() - end) - end + local current = StatsBar.getCurrentStatsBarWithPosition() - if not (current) or current:getId() ~= 'defaultOnTop' then - menu:addOption(tr('Switch to Default Style'), function() - StatsBar.hideAll() - constructDefaultOnTop() - end) - end + local menuOptions = getStatsBarMenuOptions(current) - if not (current) or current:getId() ~= 'largeOnTop' then - menu:addOption(tr('Switch to Large Style'), function() + -- Add options to the menu based on the current stats bar + for _, option in ipairs(menuOptions) do + menu:addOption(tr(option.label), function() StatsBar.hideAll() - constructLargeOnTop() - end) - end - - if not (current) or current:getId() ~= 'parallelOnTop' then - menu:addOption(tr('Switch to Parallel Style'), function() - StatsBar.hideAll() - constructParallelOnTop() + constructStatsBar(option.dimension, option.placement) end) end menu:addSeparator() - local current = StatsBar.getCurrentStatsBar() + local current = StatsBar.getCurrentStatsBarWithPosition() if current and current.skills then for _, skillTuple in ipairs(skillsTuples) do if not g_settings.getBoolean('top_statsbar_' .. skillTuple.key) then @@ -420,12 +421,52 @@ local function openDropMenu(mousePos) menu:addSeparator() menu:addOption(tr('Hide Customisable Status Bars'), function() StatsBar.hideAll() - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) + modules.game_healthcircle.setStatsBarOption("hide") end) menu:display(mousePos) end +function shouldAddStatsBarOption(current, placement, style) + local id = current:getId() + return string.find(id, placement) and id ~= style +end + +function getStatsBarMenuOptions(current) + local optionsMenu = {} + + -- Create options available based on statsBarsPlacements and statsBarsDimensions tables. + for _, placement in ipairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local style = tostring(dimension):gsub("^%u", string.lower) .. 'On' .. placement + if shouldAddStatsBarOption(current, placement, style) then + optionsMenu[#optionsMenu+1] = { + label = 'Switch to ' .. tostring(dimension) .. ' Style', + dimension = dimension, + placement = placement:gsub("^%u", string.lower), + style = style + } + end + end + end + + -- Create options available to switch placements keeping the same style + -- i.e. from bottom to top // from top to bottom + for _, placement in ipairs(statsBarsPlacements) do + if not string.find(current:getId(), placement) then + optionsMenu[#optionsMenu+1] = { + label = 'Switch to ' .. placement .. ' Style', + dimension = currentStats.dimension:gsub("^%l", string.upper), + placement = placement:gsub("^%u", string.lower), + construct = constructStatsBar, + style = current:getId() + } + end + end + + return optionsMenu +end + local function onStatsMousePress(tab, mousePos, mouseButton) if mouseButton == MouseRightButton then openDropMenu(mousePos) @@ -434,92 +475,111 @@ local function onStatsMousePress(tab, mousePos, mouseButton) end function StatsBar.reloadCurrentTab() - if currentStats.placement == 'top' then - if currentStats.dimension == 'large' then - return constructLargeOnTop() - elseif currentStats.dimension == 'parallel' then - return constructParallelOnTop() - elseif currentStats.dimension == 'default' then - return constructDefaultOnTop() - elseif currentStats.dimension == 'compact' then - return constructCompactOnTop() - end + local dimension = currentStats.dimension:gsub("^%l", string.upper) + if statsBarsDimensions[dimension] then + return constructStatsBar(dimension, currentStats.placement) + else + print("No stats bars dimensions found: ", dimension, " on reloadCurrentTab()") + return end end -function StatsBar.setStatsBarOption(dimension, placement) +function StatsBar.updateStatsBarOption(dimension) StatsBar.hideAll() - if firstCall then - if g_settings.getString('top_statsbar_dimension') and g_settings.getString('top_statsbar_dimension') ~= "" then - dimension = g_settings.getString('top_statsbar_dimension') - else - dimension = "compact" - end + StatsBar.firstLoadSettings() - firstCall = false + if currentStats.dimension ~= "hide" and dimension ~= "hide" then + StatsBar.reloadCurrentTab() end +end +local function getSettingOrDefault(setting, default) + local value = g_settings.getString(setting) + return value ~= "" and value or default +end + +local function setSetting(setting, value) + g_settings.set(setting, value) +end + +function StatsBar.loadSettings() currentStats = { - dimension = dimension, - placement = placement + dimension = getSettingOrDefault('statsbar_dimension', "compact"), + placement = getSettingOrDefault('statsbar_placement', "top") } - g_settings.set('top_statsbar_dimension', currentStats.dimension) - g_settings.set('top_statsbar_placement', currentStats.placement) +end - if dimension ~= "hide" then - StatsBar.reloadCurrentTab() +function StatsBar.saveSettings() + setSetting('statsbar_dimension', currentStats.dimension) + setSetting('statsbar_placement', currentStats.placement) +end + +function StatsBar.firstLoadSettings() + if firstCall then + currentStats.dimension = getSettingOrDefault("statsbar_dimension", "compact") + currentStats.placement = getSettingOrDefault("statsbar_placement", "top") + + firstCall = false end + StatsBar.saveSettings() + StatsBar.loadSettings() end function StatsBar.OnGameEnd() - g_settings.set('top_statsbar_dimension', currentStats.dimension) - g_settings.set('top_statsbar_placement', currentStats.placement) - + StatsBar.saveSettings() StatsBar.hideAll() modules.game_inventory.getIconsPanelOn():destroyChildren() modules.game_inventory.getIconsPanelOff():destroyChildren() - statsBar.largeOnTop.icons:destroyChildren() - statsBar.parallelOnTop.icons:destroyChildren() - statsBar.defaultOnTop.icons:destroyChildren() - statsBar.compactOnTop.icons:destroyChildren() + StatsBar.destroyAllIcons() end function StatsBar.OnGameStart() - currentStats = { - dimension = g_settings.getString('top_statsbar_dimension'), - placement = g_settings.getString('top_statsbar_placement') - } - - if not (currentStats.dimension) or not (currentStats.placement) or currentStats.dimension == '' or - currentStats.placement == '' then - currentStats = { - dimension = 'default', - placement = 'top' - } - end + StatsBar.loadSettings() createBlankIcon() StatsBar.reloadCurrentTab() - modules.game_healthcircle.setTopBarOption(currentStats.dimension, currentStats.placement) + modules.game_healthcircle.setStatsBarOption() +end +function createStatsBarWidgets(statsBar) + -- This method will create the widgets based on the statsBar, statsBarsPlacements and statsBarsDimensions tables. + local widget = statsBar + for _, placement in ipairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local elementName = tostring(dimension):gsub("^%u", string.lower) .. "On" .. placement + widget[elementName] = statsBar:getChildById(elementName) + end + end + widget.onMousePress = onStatsMousePress + return widget end function StatsBar.init() - statsBar = modules.game_interface.getGameTopStatsBar() - if not statsBar then + statsBarTop = modules.game_interface.getGameTopStatsBar() + statsBarBottom = modules.game_interface.getGameBottomStatsBar() + + statsBars = { + statsBarTop = statsBarTop, + statsBarBottom = statsBarBottom + } + + if not statsBarTop then return end - statsBar.largeOnTop = statsBar:getChildById('largeOnTop') - statsBar.parallelOnTop = statsBar:getChildById('parallelOnTop') - statsBar.defaultOnTop = statsBar:getChildById('defaultOnTop') - statsBar.compactOnTop = statsBar:getChildById('compactOnTop') - statsBar.onMousePress = onStatsMousePress - StatsBar.hideAll() - connect(LocalPlayer, { + if not statsBarBottom then + return + end + + -- Create widgets based on statsBars table. + for _, statBar in pairs(statsBars) do + statBar = createStatsBarWidgets(statBar) + end + + statsBarDeepInfo = { onExperienceChange = StatsBar.reloadCurrentStatsBarDeepInfo, onLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo, onHealthChange = StatsBar.reloadCurrentStatsBarQuickInfo, @@ -529,29 +589,67 @@ function StatsBar.init() onSkillChange = StatsBar.reloadCurrentStatsBarDeepInfo, onBaseSkillChange = StatsBar.reloadCurrentStatsBarDeepInfo, onStatesChange = StatsBar.reloadCurrentStatsBarQuickInfo_state + } - }) + StatsBar.hideAll() + connect(LocalPlayer, statsBarDeepInfo) connect(g_game, { onGameStart = StatsBar.OnGameStart, onGameEnd = StatsBar.OnGameEnd }) end +function StatsBar.hideAll() + -- This iterates between the tables: statsBar -> statsBarsPlacements -> statsBarsDimensions + -- And hides all the stats bars based on these tables. + for _, bar in pairs(statsBars) do + for _, placement in pairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local key = tostring(dimension):lower() .. "On" .. placement + if bar[key] and bar[key].skills then + bar[key].skills:destroyChildren() + bar[key].skills:setHeight(0) + bar[key]:setHeight(0) + bar[key]:hide() + end + end + end + bar:setHeight(0) + end +end + +function StatsBar.destroyAllIcons() + -- This iterates between the tables: statsBar -> statsBarsPlacements -> statsBarsDimensions + -- And destroy all icons based on these tables. + for _, bar in pairs(statsBars) do + for _, placement in pairs(statsBarsPlacements) do + for dimension, _ in pairs(statsBarsDimensions) do + local key = tostring(dimension):lower() .. "On" .. placement + if bar[key] and bar[key].skills then + bar[key].icons:destroyChildren() + end + end + end + bar:setHeight(0) + end +end + +function StatsBar.destroyAllBars() + -- This iterates between the tables: statsBars + -- And destroy all bars based on these tables. + for _, bar in pairs(statsBars) do + bar:destroy() + end +end + function StatsBar.terminate() - disconnect(LocalPlayer, { - onExperienceChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onHealthChange = StatsBar.reloadCurrentStatsBarQuickInfo, - onManaChange = StatsBar.reloadCurrentStatsBarQuickInfo, - onMagicLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onBaseMagicLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onSkillChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onBaseSkillChange = StatsBar.reloadCurrentStatsBarDeepInfo, - onStatesChange = StatsBar.reloadCurrentStatsBarQuickInfo_state - }) + StatsBar.saveSettings() + + disconnect(LocalPlayer, statsBarDeepInfo) disconnect(g_game, { onGameStart = StatsBar.OnGameStart, OnGameEnd = StatsBar.OnGameEnd }) - statsBar:destroy() + + StatsBar.destroyAllBars() end