otclient-redemption/modules/game_interface/widgets/statsbar.lua
Eduardo Dantas 46b21f0166 test base1
2026-01-06 11:48:00 -03:00

961 lines
35 KiB
Lua

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"
}
local skillsLineHeight = 20
local skillsTuples = {
{ skill = nil, key = 'experience', icon = '/images/icons/icon_experience', placement = 'center', order = 0, name = "Level" },
{ skill = nil, key = 'magic', icon = '/images/icons/icon_magic', placement = 'left', order = 1, name = "Magic Level" },
{ skill = Skill.Axe, key = 'axe', icon = '/images/icons/icon_axe', placement = 'right', order = 1, name = "Axe Fighting Skill" },
{ skill = Skill.Club, key = 'club', icon = '/images/icons/icon_club', placement = 'left', order = 2, name = "Club Fighting Skill" },
{ skill = Skill.Distance, key = 'distance', icon = '/images/icons/icon_distance', placement = 'right', order = 2, name = "Distance Fighting Skill" },
{ skill = Skill.Fist, key = 'fist', icon = '/images/icons/icon_fist', placement = 'left', order = 3, name = "Fist Fighting Skill" },
{ skill = Skill.Shielding, key = 'shielding', icon = '/images/icons/icon_shielding', placement = 'right', order = 3, name = "Shielding Fighting Skill" },
{ skill = Skill.Sword, key = 'sword', icon = '/images/icons/icon_sword', placement = 'left', order = 4, name = "Sword Fighting Skill" },
{ skill = Skill.Fishing, key = 'fishing', icon = '/images/icons/icon_fishing', placement = 'right', order = 4, name = "Fishing Fighting Skill" },
}
StatsBar = {}
local lastProficiencyCache = {}
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
end
local tuples = {}
for i = 1, #skillsTuples do
local skillTuple = skillsTuples[i]
if skillTuple and g_settings.getBoolean('top_statsbar_' .. skillTuple.key) then
table.insert(tuples, skillTuple)
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()
local lines = 0
local lastPlacement = 'left'
for i = 1, #tuples do
local skillTuple = tuples[i]
local widget = g_ui.createWidget('TopStatsSkillElement', skills)
widget:setId('statsbar_skill_' .. skillTuple.key)
widget:addAnchor(AnchorTop, 'parent', AnchorTop)
if lastPlacement == 'left' then
widget:setMarginTop(lines * skillsLineHeight)
else
widget:setMarginTop((lines - 1) * skillsLineHeight)
end
widget.level = widget:getChildById('level')
widget.icon = widget:getChildById('icon')
widget.bar = widget:getChildById('bar')
widget.icon:setImageSource(skillTuple.icon)
widget.icon:setTooltip(skillTuple.name)
widget.bar.statsGrade = 4
widget.bar.statsGradeColor = '#070707ff'
widget.bar:reloadBorder()
widget.bar.showText = false
if skillTuple.key == 'experience' then
widget.bar.statsType = 'experience'
else
widget.bar.statsType = 'skill'
end
if skillTuple.placement == 'center' or (i == #tuples and lastPlacement == 'left') then
widget:addAnchor(AnchorLeft, 'parent', AnchorLeft)
widget:addAnchor(AnchorRight, 'parent', AnchorRight)
lines = lines + 1
elseif lastPlacement == 'left' then
widget:addAnchor(AnchorLeft, 'parent', AnchorLeft)
widget:addAnchor(AnchorRight, 'parent', AnchorHorizontalCenter)
lines = lines + 1
lastPlacement = 'right'
elseif lastPlacement == 'right' then
widget:addAnchor(AnchorRight, 'parent', AnchorRight)
widget:addAnchor(AnchorLeft, 'parent', AnchorHorizontalCenter)
lastPlacement = 'left'
end
if skillTuple.key == 'experience' then
widget.level:setText(player:getLevel())
widget.bar:setValue(player:getLevelPercent(), 100)
elseif skillTuple.key == 'magic' then
widget.level:setText(player:getMagicLevel())
widget.bar:setValue(player:getMagicLevelPercent(), 100)
else
widget.level:setText(player:getSkillLevel(skillTuple.skill))
widget.bar:setValue(player:getSkillLevelPercent(skillTuple.skill), 100)
end
end
skills:setHeight((lines * skillsLineHeight) + 5)
parent:setHeight(40 + skills:getHeight())
statsBar:setHeight(statsBar:getHeight() + skills:getHeight())
end
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' or 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 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' or 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
end
function StatsBar.reloadCurrentStatsBarQuickInfo()
local player = g_game.getLocalPlayer()
if not player then
return
end
local bar = StatsBar.getCurrentStatsBarWithPosition()
if not bar then
return
end
local mana = player:getMana()
local maxMana = player:getMaxMana()
bar.health:setValue(player:getHealth(), player:getMaxHealth())
local manashield = 0
local maxManaShield = 0
if player.getManaShield then
manashield = player:getManaShield()
end
if not bar.mana.defaultHeight then
bar.mana.defaultHeight = bar.mana:getHeight()
end
bar.mana:setValue(mana, maxMana)
if player.getMaxManaShield then
maxManaShield = player:getMaxManaShield()
end
local shouldShowManaShield = manashield > 0 and maxManaShield > 0
if shouldShowManaShield then
local fullHeight = bar.mana.defaultHeight
local manaHeight = math.floor(fullHeight / 2)
local shieldHeight = math.max(1, fullHeight - manaHeight)
bar.mana.showText = false
if bar.mana.text then
bar.mana.text:hide()
end
bar.mana:setHeight(manaHeight)
bar.manashield:show()
bar.manashield:setMarginTop(0)
bar.manashield:setHeight(shieldHeight)
bar.manashield:setValue(manashield, maxManaShield)
if bar.manashield.text then
bar.manashield.text:setWidth(400)
local textOffset = math.floor(manaHeight / 2)
local manaText = string.format('%d/%d (%d/%d)', mana, maxMana, manashield, maxManaShield)
if not bar.manashield or not bar.manashield.text then
return
end
bar.manashield.text:setMarginTop(-textOffset)
bar.manashield.text:setMarginBottom(0)
bar.manashield.text:show()
bar.manashield.text:raise()
bar.manashield.showText = true
bar.manashield.manaShieldText = manaText
end
else
bar.mana.showText = true
if bar.mana.defaultHeight then
bar.mana:setHeight(bar.mana.defaultHeight)
end
bar.manashield:setMarginTop(0)
bar.manashield:setHeight(0)
bar.manashield:hide()
bar.manashield.showText = true
if bar.manashield.text then
bar.manashield.text:hide()
bar.manashield.text:setMarginTop(0)
bar.manashield.text:setMarginBottom(0)
end
end
if not shouldShowManaShield and bar.mana.text then
bar.mana.text:show()
end
end
local function loadIcon(bitChanged, content, topmenu)
local icon = g_ui.createWidget('ConditionWidget', content)
icon:setId(Icons[bitChanged].id)
icon:setImageSource("/images/game/states/player-state-flags")
icon:setImageClip(((Icons[bitChanged].clip - 1) * 9) .. ' 0 9 9')
local tooltip = Icons[bitChanged].tooltip
if tooltip == "You are GoshnarTaint" then
tooltip = "Goshnar's Lairs Penalties:\n" ..
"- 10% chance of creature teleportation to you\n" ..
"- 0.5% chance of new creature spawn when hitting another\n" ..
"- 15% increased damage received\n" ..
"- 10% chance of creature full heal instead of dying\n" ..
"- Lose 10% of current HP and mana every 10 seconds"
end
icon:setTooltip(tooltip)
icon:setImageSize(tosize("9 9"))
icon:setMarginRight(-1)
if topmenu then
icon:setMarginTop(5)
icon:setMarginLeft(2)
icon:setMarginRight(-2)
end
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 = getStatsBarsIconContent()
local iconId = Icons[bitChanged]
if not iconId then
g_logger.warning(string.format("No icon ID %s (%s) found. Check Icons array in modules/gamelib/player.lua.",
tostring(bitChanged), tostring(math.log(bitChanged) / math.log(2))))
return
end
for _, contentData in ipairs(contents) do
local icon = contentData.content:getChildById(iconId.id)
if icon then
icon:destroy()
else
icon = loadIcon(bitChanged, contentData.content, contentData.loadIconTransparent)
icon:setParent(contentData.content)
end
end
end
function processIcon(id, action, createIfMissing)
-- game_rewardwall
for _, contentData in ipairs(getStatsBarsIconContent()) do
local icon = contentData.content:getChildById(id)
if icon then
action(icon)
elseif createIfMissing then
icon = loadIcon(id, contentData.content, contentData.loadIconTransparent)
icon:setParent(contentData.content)
action(icon)
end
end
end
function StatsBar.reloadCurrentStatsBarQuickInfo_state(localPlayer, now, old)
local player = g_game.getLocalPlayer()
if not player then
return
end
if now == old then
return
end
Player.iterateChangedStates(now, old, function(bitChanged)
toggleIcon(bitChanged)
end)
end
function StatsBar.reloadCurrentStatsBarDeepInfo()
local player = g_game.getLocalPlayer()
if not player then
return
end
local bar = StatsBar.getCurrentStatsBarWithPosition()
if not bar then
return
end
for _, skillTuple in ipairs(skillsTuples) do
local widget = bar:recursiveGetChildById('statsbar_skill_' .. skillTuple.key)
if widget then
if skillTuple.key == 'experience' then
widget.level:setText(player:getLevel())
widget.bar:setValue(player:getLevelPercent(), 100)
elseif skillTuple.key == 'magic' then
widget.level:setText(player:getMagicLevel())
widget.bar:setValue(player:getMagicLevelPercent(), 100)
else
widget.level:setText(player:getSkillLevel(skillTuple.skill))
widget.bar:setValue(player:getSkillLevelPercent(skillTuple.skill), 100)
end
end
end
end
function constructStatsBar(dimension, placement)
local dimensionString = dimension:gsub("^%u", string.lower)
StatsBar.updateCurrentStats(dimensionString, placement)
local dimensionOnPlacement = dimensionString:gsub("^%u", string.lower) .. "On" .. placement:gsub("^%l", string.upper)
local statsBar = statsBars["statsBar" .. placement:gsub("^%l", string.upper)]
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].manashield = statsBar[dimensionOnPlacement]:getChildById('manashield')
statsBar[dimensionOnPlacement].skills = statsBar[dimensionOnPlacement]:getChildById('skills')
reloadSkillsTab(statsBar[dimensionOnPlacement].skills, statsBar[dimensionOnPlacement])
StatsBar.reloadCurrentStatsBarQuickInfo()
StatsBar.switchCurrentLayout()
modules.game_topbar.setStatsBarOption()
else
print("No stats bar found for:", dimensionOnPlacement .. " on constructStatsBar()")
end
end
function StatsBar.updateCurrentStats(dimension, placement)
currentStats = {
dimension = dimension,
placement = placement
}
end
local function openDropMenu(mousePos)
local menu = g_ui.createWidget('PopupMenu')
menu:setGameMenu(true)
local current = StatsBar.getCurrentStatsBarWithPosition()
local menuOptions = getStatsBarMenuOptions(current)
-- 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()
constructStatsBar(option.dimension, option.placement)
end)
end
menu:addSeparator()
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
menu:addOption(tr('Show') .. ' ' .. tr(skillTuple.name), function()
g_settings.set('top_statsbar_' .. skillTuple.key, true)
reloadSkillsTab(current.skills, current)
end)
else
menu:addOption(tr('Hide') .. ' ' .. tr(skillTuple.name), function()
g_settings.set('top_statsbar_' .. skillTuple.key, false)
reloadSkillsTab(current.skills, current)
end)
end
end
end
menu:addSeparator()
menu:addOption(tr('Hide Customisable Status Bars'), function()
StatsBar.hideAll()
modules.game_topbar.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)
return true
end
end
function StatsBar.reloadCurrentTab()
if currentStats.dimension == "hide" then
return
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.updateStatsBarOption(dimension)
StatsBar.hideAll()
StatsBar.firstLoadSettings()
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 = getSettingOrDefault('statsbar_dimension', "compact"),
placement = getSettingOrDefault('statsbar_placement', "top")
}
end
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()
StatsBar.saveSettings()
StatsBar.hideAll()
modules.game_inventory.getIconsPanelOn():destroyChildren()
modules.game_inventory.getIconsPanelOff():destroyChildren()
StatsBar.destroyAllIcons()
end
function StatsBar.OnGameStart()
StatsBar.loadSettings()
StatsBar.reloadCurrentTab()
modules.game_topbar.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()
statsBarTop = modules.game_interface.getGameTopStatsBar()
statsBarBottom = modules.game_interface.getGameBottomStatsBar()
statsBars = {
statsBarTop = statsBarTop,
statsBarBottom = statsBarBottom
}
if not statsBarTop then
return
end
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,
onManaChange = StatsBar.reloadCurrentStatsBarQuickInfo,
onManaShieldChange = StatsBar.reloadCurrentStatsBarQuickInfo,
onMagicLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo,
onBaseMagicLevelChange = StatsBar.reloadCurrentStatsBarDeepInfo,
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()
StatsBar.saveSettings()
disconnect(LocalPlayer, statsBarDeepInfo)
disconnect(g_game, {
onGameStart = StatsBar.OnGameStart,
OnGameEnd = StatsBar.OnGameEnd
})
StatsBar.destroyAllBars()
end
function StatsBar.onHungryChange(regenerationTime, alert)
local contents = getStatsBarsIconContent()
local info = Icons[PlayerStates.Hungry]
if regenerationTime <= alert then
for _, contentData in ipairs(contents) do
local icon = contentData.content:getChildById(info.id)
if not icon then
icon = g_ui.createWidget('ConditionWidget', contentData.content)
icon:setId(info.id)
icon:setImageSource("/images/game/states/player-state-flags")
icon:setImageClip(((info.clip - 1) * 9) .. ' 0 9 9')
icon:setTooltip(info.tooltip)
icon:setImageSize(tosize("9 9"))
if contentData.loadIconTransparent then
icon:setMarginTop(5)
end
end
end
else
for _, contentData in ipairs(contents) do
local icon = contentData.content:getChildById(info.id)
if icon then
icon:destroy()
icon = nil
end
end
end
end
-- Proficiency integration
function StatsBar.switchCurrentLayout()
if table.empty(lastProficiencyCache) then
return
end
-- No layout large, compact e parallel, garantir que nenhum elemento de progresso seja exibido
if currentStats.dimension == "large" or currentStats.dimension == "compact" or currentStats.dimension == "parallel" then
local statsBar = StatsBar.getCurrentStatsBarWithPosition and StatsBar.getCurrentStatsBarWithPosition()
if statsBar then
local percentBar = statsBar:recursiveGetChildById('starProgress')
local percentLabel = statsBar:recursiveGetChildById('proficiencyLabel')
local proficiencyIcon = statsBar:recursiveGetChildById('proficiencyIcon')
local proficiencyBg = statsBar:recursiveGetChildById('proficiencyBg')
if percentBar then percentBar:setVisible(false) end
if percentLabel then percentLabel:setVisible(false) end
if proficiencyIcon then proficiencyIcon:setVisible(false) end
if proficiencyBg then proficiencyBg:setVisible(false) end
-- Atualizar o highlight se houver dados em cache
if not table.empty(lastProficiencyCache) then
local highlightButton = statsBar:recursiveGetChildById('highlightProficiencyButton')
if highlightButton then
highlightButton:setVisible(lastProficiencyCache.hasUnnusedPerk)
end
end
end
end
StatsBar.onUpdateProficiencyData(lastProficiencyCache.itemCache, lastProficiencyCache.hasUnnusedPerk,
lastProficiencyCache.thingType)
end
function onUpdateProficiencyWidget(hidePercentBar)
local statsBar = StatsBar.getCurrentStatsBarWithPosition()
if not statsBar then return end
local statsPanel = statsBar:recursiveGetChildById('stats')
local proficiencyPanel = statsBar:recursiveGetChildById('proficiencyPanel')
local proficiencyButton = statsBar:recursiveGetChildById('proficiencyButton')
if not proficiencyPanel or not proficiencyButton then
return
end
-- No layout large, compact e parallel, apenas mostrar/ocultar o botão
if currentStats.dimension == "large" or currentStats.dimension == "compact" or currentStats.dimension == "parallel" then
proficiencyButton:setVisible(not hidePercentBar)
proficiencyPanel:setVisible(not hidePercentBar)
-- Garantir que nenhum elemento de progresso seja exibido
local percentBar = statsBar:recursiveGetChildById('starProgress')
local percentLabel = statsBar:recursiveGetChildById('proficiencyLabel')
local proficiencyIcon = statsBar:recursiveGetChildById('proficiencyIcon')
local proficiencyBg = statsBar:recursiveGetChildById('proficiencyBg')
if percentBar then percentBar:setVisible(false) end
if percentLabel then percentLabel:setVisible(false) end
if proficiencyIcon then proficiencyIcon:setVisible(false) end
if proficiencyBg then proficiencyBg:setVisible(false) end
-- Atualizar o highlight se houver dados em cache
if not table.empty(lastProficiencyCache) then
local highlightButton = statsBar:recursiveGetChildById('highlightProficiencyButton')
if highlightButton then
highlightButton:setVisible(lastProficiencyCache.hasUnnusedPerk)
end
end
return
end
-- Para outros layouts, atualiza o painel completo
if currentStats.dimension == "default" then
if hidePercentBar then
if statsPanel then
statsPanel:setMarginRight(45)
end
proficiencyPanel:setSize(tosize("0 13"))
proficiencyButton:setMarginRight(-4)
else
if statsPanel then
statsPanel:setMarginRight(-14)
end
proficiencyPanel:setSize(tosize("103 13"))
proficiencyPanel:setMarginRight(8)
proficiencyButton:setMarginRight(3)
end
end
end
function StatsBar.onUpdateProficiencyData(itemCache, hasUnnusedPerk, thingType)
local statsBar = StatsBar.getCurrentStatsBarWithPosition and StatsBar.getCurrentStatsBarWithPosition()
if not statsBar or not itemCache or not thingType then return end
local highlightButton = statsBar:recursiveGetChildById('highlightProficiencyButton')
local percentBar = statsBar:recursiveGetChildById('starProgress')
local percentLabel = statsBar:recursiveGetChildById('proficiencyLabel')
local proficiencyIcon = statsBar:recursiveGetChildById('proficiencyIcon')
-- No layout large, compact e parallel, apenas atualiza o highlight do botão e retorna imediatamente
if currentStats.dimension == "large" or currentStats.dimension == "compact" or currentStats.dimension == "parallel" then
-- Garantir que nenhum elemento de progresso seja exibido no layout large/compact
if percentBar then percentBar:setVisible(false) end
if percentLabel then percentLabel:setVisible(false) end
if proficiencyIcon then proficiencyIcon:setVisible(false) end
local proficiencyBg = statsBar:recursiveGetChildById('proficiencyBg')
if proficiencyBg then proficiencyBg:setVisible(false) end
-- Atualizar o highlight do botão
-- Se não encontrou na primeira busca, tentar buscar novamente
if not highlightButton then
highlightButton = statsBar:recursiveGetChildById('highlightProficiencyButton')
end
if highlightButton then
highlightButton:setVisible(hasUnnusedPerk)
end
if modules.game_sidebuttons and modules.game_sidebuttons.onProficiencyHighlight then
modules.game_sidebuttons.onProficiencyHighlight(hasUnnusedPerk)
end
lastProficiencyCache = { itemCache = itemCache, hasUnnusedPerk = hasUnnusedPerk, thingType = thingType }
return
end
-- Check if module is properly loaded and initialized
if not modules.game_proficiency or
not modules.game_proficiency.ProficiencyData or
type(modules.game_proficiency.ProficiencyData) ~= 'table' then
-- Module not loaded or not properly initialized - hide all proficiency UI elements
if highlightButton then highlightButton:setVisible(false) end
if percentBar then percentBar:setVisible(false) end
if percentLabel then percentLabel:setVisible(false) end
if proficiencyIcon then proficiencyIcon:setVisible(false) end
return
end
local proficiencyId = thingType:getProficiencyId()
if not proficiencyId or proficiencyId == 0 then return end
local perkCount = modules.game_proficiency.ProficiencyData:getPerkLaneCount(proficiencyId) or 0
if perkCount == 0 then return end
local item = Item.create(thingType:getId())
if not item then return end
local maxAvailableLevel = perkCount + 2
local weaponLevel = modules.game_proficiency.ProficiencyData:getCurrentLevelByExp(item, itemCache.exp or 0, true)
local nextLevel = math.min(maxAvailableLevel, weaponLevel + 1)
local percent = modules.game_proficiency.ProficiencyData:getLevelPercent(itemCache.exp or 0, nextLevel, item)
local maxLevelExperience = modules.game_proficiency.ProficiencyData:getMaxExperienceByLevel(nextLevel, item)
if percentBar then
percentBar:setPercent(percent)
percentBar:setTooltip(string.format("Proficiency Progress: %s / %s", comma_value(itemCache.exp or 0),
comma_value(maxLevelExperience)))
end
if percentLabel then
percentLabel:setText(percent .. "%")
end
if highlightButton then
highlightButton:setVisible(hasUnnusedPerk)
end
if proficiencyIcon then
proficiencyIcon:setOn(hasUnnusedPerk)
end
if modules.game_sidebuttons and modules.game_sidebuttons.onProficiencyHighlight then
modules.game_sidebuttons.onProficiencyHighlight(hasUnnusedPerk)
end
lastProficiencyCache = { itemCache = itemCache, hasUnnusedPerk = hasUnnusedPerk, thingType = thingType }
end
function StatsBar.clearProficiencyCache()
lastProficiencyCache = {}
local statsBar = StatsBar.getCurrentStatsBar and StatsBar.getCurrentStatsBar()
if statsBar then
local percentBar = statsBar:recursiveGetChildById('starProgress')
local percentLabel = statsBar:recursiveGetChildById('proficiencyLabel')
local highlightButton = statsBar:recursiveGetChildById('highlightProficiencyButton')
local proficiencyIcon = statsBar:recursiveGetChildById('proficiencyIcon')
if percentBar then
percentBar:setPercent(0)
percentBar:setTooltip("")
end
if percentLabel then
percentLabel:setText("0%")
end
if highlightButton then
highlightButton:setVisible(false)
end
if proficiencyIcon then
proficiencyIcon:setOn(false)
end
end
end