• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

OTClient Exp Analyzer Button and Reset Button

potinho

Intermediate OT User
Joined
Oct 11, 2009
Messages
1,343
Solutions
17
Reaction score
127
Location
Brazil
Hi guys, how are you?

I have implemented on my server an exp analyzer module, seems works, but button goes weird when i press it to open, like image bellow:

btn closed:
1657639502159.png

btn opened:
1657639522427.png

I want to add a button named "reset" on XP static too, to reset session to 0. Can u guys help me? Follow files:

exph.lua
Lua:
exphWindow = nil
exphButton = nil

function init()
  connect(LocalPlayer, {
    onExperienceChange = onExperienceChange
  })
  
  connect(g_game, {
    onGameStart = refresh,
    onGameEnd = offline
  })
  
  exphWindow = g_ui.loadUI('exph', modules.game_interface.getRightPanel())
  exphButton =  modules.client_topmenu.addRightGameToggleButton('exphButton', tr('Experience Analyzer (Ctrl+H)'), '/images/topbuttons/exph', toggle)
  exphButton:setOn(exphWindow:isVisible())
  g_keyboard.bindKeyDown('Ctrl+H', toggle)

  --refresh()
  exphWindow:setup()
  
  startFreshExpHWindow()
  
end

--//########## REAL MAGIC ##########//--
expHUpdateEvent = 0
expHVar = {
    originalExpAmount = 0,
    lastExpAmount = 0,
    historyIndex = 0,
    sessionStart = 0,
}
expHistory = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

function startFreshExpHWindow()
    resetExpH()
    if expHUpdateEvent ~= 0 then
        removeEvent(expHUpdateEvent)
    end
    updateExpHWindow()
end

function updateExpHWindow()
    expHUpdateEvent = scheduleEvent(updateExpHWindow, 5000)
    local player = g_game.getLocalPlayer()
    if not player then return end --Wont go future if there's no player
  
    local currentExp = player:getExperience()
    if expHVar.lastExpAmount == 0 then
        expHVar.lastExpAmount = currentExp
    end
    if expHVar.originalExpAmount == 0 then
        expHVar.originalExpAmount = currentExp
    end
    local expDiff = math.floor(currentExp-expHVar.lastExpAmount)
    updateExpHistory(expDiff)
    expHVar.lastExpAmount = currentExp
    
    local _expGained = math.floor(currentExp-expHVar.originalExpAmount)
    
    local _expHistory = getExpGained()
    if _expHistory <= 0 and (expHVar.sessionStart > 0 or _expGained > 0) then --No Exp gained last 5 min, lets stop
        resetExpH()
        return false
    end
    
    local _session = 0
    local _start = expHVar.sessionStart
    if _start > 0 and _expGained > 0 then
        _session = math.floor(g_clock.seconds()-_start)
    end
    
    local string_session = getTimeFormat(_session)
    local string_expGain = number_format(_expGained)
    -----------------------------------------------------
    local _getExpHour = getExpPerHour(_expHistory, _session)
    local string_expph = number_format(_getExpHour)
    -----------------------------------------------------

    local _lvl = player:getLevel()
    local _nextLevelExp = getExperienceForLevel(_lvl+1)
    local _expToNextLevel = math.floor(_nextLevelExp-currentExp)
    
    local string_exptolevel = number_format(_expToNextLevel)
    
    local _timeToNextLevel = getNextLevelTime(_expToNextLevel, _getExpHour)
    local string_timetolevel = getTimeFormat(_timeToNextLevel)
    
    setSkillValue('session',        string_session)
    setSkillValue('expph',            string_expph)
    setSkillValue('expgained',        string_expGain)
    setSkillValue('exptolevel',        string_exptolevel)
    setSkillValue('timetolevel',    string_timetolevel)
end

function getNextLevelTime(_expToNextLevel, _getExpHour)
    if _getExpHour <= 0 then
        return 0
    end
    local _expperSec = (_getExpHour/3600)
    local _secToNextLevel = math.ceil(_expToNextLevel/_expperSec)
    return _secToNextLevel
end

function getExperienceForLevel(lv)
    lv = lv - 1
    return ((50 * lv * lv * lv) - (150 * lv * lv) + (400 * lv)) / 3
end

function getNumber(msg)
    b, e = string.find(msg, "%d+")
    
    if b == nil or e == nil then
        count = 0
    else
        count = tonumber(string.sub(msg, b, e))
    end    
    return count
end

function number_format(amount)
  local formatted = amount
  while true do
    formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
    if (k==0) then
      break
    end
  end
  return formatted
end

function getExpPerHour(_expHistory, _session)
    if _session < 10 then
        _session = 10
    elseif _session > 300 then
        _session = 300
    end
    
    local _expSec = _expHistory/_session
    local _expH = math.floor(_expSec*3600)
    if _expH <= 0 then
        _expH = 0
    end
    return getNumber(_expH)
end

function getTimeFormat(_secs)
    local _hour = math.floor(_secs/3600)
    _secs = math.floor(_secs-(_hour*3600))
    local _min = math.floor(_secs/60)
    
    if _hour <= 0 then
        _hour = "00"
    elseif _hour <= 9 then
        _hour = "0".. _hour
    end
    if _min <= 0 then
        _min = "00"
    elseif _min <= 9 then
        _min = "0".. _min
    end
    return _hour ..":".. _min
end

function updateExpHistory(dif)
    if dif > 0 then
        if expHVar.sessionStart == 0 then
            expHVar.sessionStart = g_clock.seconds()
        end
    end
    
    local _index = expHVar.historyIndex
    expHistory[_index] = dif
    _index = _index+1
    if _index < 0 or _index > 59 then
        _index = 0
    end
    expHVar.historyIndex = _index
end

function getExpGained()
    local totalExp = 0
    for key,value in pairs(expHistory) do
        totalExp = totalExp+value
    end
    return totalExp
end

function resetExpH()
    expHVar.originalExpAmount = 0
    expHVar.lastExpAmount = 0
    expHVar.historyIndex = 0
    expHVar.sessionStart = 0

    setSkillValue('session',        "00:00")
    setSkillValue('expph',            0)            setSkillColor('expph',            '#1eff00')
    setSkillValue('expgained',        0)            setSkillColor('expgained',        '#d8ff00')
    setSkillValue('exptolevel',        0)            setSkillColor('exptolevel',        '#ff9600')
    setSkillValue('timetolevel',    "00:00")    setSkillColor('timetolevel',    '#ff6767')
    
    for key,value in pairs(expHistory) do
        value = 0
    end
end
--//########## REAL MAGIC ##########//--

function terminate()
  disconnect(LocalPlayer, {
    onExperienceChange = onExperienceChange
  })
  disconnect(g_game, {
    onGameStart = refresh,
    onGameEnd = offline
  })

  g_keyboard.unbindKeyDown('Ctrl+H')
  exphWindow:destroy()
  exphButton:destroy()
end

function expForLevel(level)
  return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200)
end

function expToAdvance(currentLevel, currentExp)
  return expForLevel(currentLevel+1) - currentExp
end

function resetSkillColor(id)
  local skill = exphWindow:recursiveGetChildById(id)
  local widget = skill:getChildById('value')
  widget:setColor('#bbbbbb')
end

function setSkillValue(id, value)
  local skill = exphWindow:recursiveGetChildById(id)
  local widget = skill:getChildById('value')
  widget:setText(value)
end

function setSkillColor(id, value)
  local skill = exphWindow:recursiveGetChildById(id)
  local widget = skill:getChildById('value')
  widget:setColor(value)
end

function setSkillTooltip(id, value)
  local skill = exphWindow:recursiveGetChildById(id)
  local widget = skill:getChildById('value')
  widget:setTooltip(value)
end

function setSkillPercent(id, percent, tooltip)
  local skill = exphWindow:recursiveGetChildById(id)
  local widget = skill:getChildById('percent')
  widget:setPercent(math.floor(percent))

  if tooltip then
    widget:setTooltip(tooltip)
  end
end

function comma_value(n)
    local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
    return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end

function onExperienceChange(localPlayer, currentExperience, print_s)
    --Not entierly sure if this is the event function whenever you gain exp ingame
end

function refresh()
    local player = g_game.getLocalPlayer()
    if not player then return end

    resetExpH()

    local contentsPanel = exphWindow:getChildById('contentsPanel')
    exphWindow:setContentMinimumHeight(44)
    exphWindow:setContentMaximumHeight(87)

    exphButton:setOn(exphWindow:isVisible())
end

function offline()
    startFreshExpHWindow()
end

function toggle()
  exphButton:setOn(not exphWindow:isVisible())
  if exphWindow:isVisible() then
      exphWindow:close()
  else
      exphWindow:open()
  end
end

function onMiniWindowClose()
    exphButton:setOn(false)
end

exph.otui

Code:
SkillFirstWidget < UIWidget

exphButton < UIButton
  height: 21
  margin-bottom: 2
  &onClick: onexphButtonClick

SkillNameLabel < GameLabel
  font: verdana-11px-antialised
  color: #AFAFAF
  anchors.left: parent.left
  anchors.top: parent.top
  anchors.bottom: parent.bottom

SkillValueLabel < GameLabel
  id: value
  font: verdana-11px-antialised
  color: #AFAFAF
  text-align: topright
  anchors.right: parent.right
  anchors.top: parent.top
  anchors.bottom: parent.bottom
  anchors.left: prev.left

SkillPercentPanel < ProgressBar
  id: percent
  image-source: /images/ui/progressbarexph
  background-color: #00C000
  border: 1 black
  height: 5
  margin-top: 15
  anchors.left: parent.left
  anchors.right: parent.right
  anchors.top: parent.top
  phantom: false

MiniWindow
  id: exphWindow
  !text: tr('XP Statistics')
  color: #8F8F8F
  height: 70
  icon: /images/topbuttons/exph
  @onClose: modules.game_exph.onMiniWindowClose()
  &save: true

  MiniWindowContents
    padding-left: 5
    padding-right: 5
    layout: verticalBox

    exphButton
      margin-top: 1
      id: session
      height: 15
      SkillNameLabel
        !text: tr('Session:')
      SkillValueLabel

    exphButton
      id: expph
      height: 15
      SkillNameLabel
        !text: tr('Exp/h:')
      SkillValueLabel

    exphButton
      id: expgained
      height: 15
      SkillNameLabel
        !text: tr('Exp Gained:')
      SkillValueLabel

    exphButton
      id: exptolevel
      height: 15
      SkillNameLabel
        !text: tr('Exp to level:')
      SkillValueLabel

    exphButton
      id: timetolevel
      height: 15
      SkillNameLabel
        !text: tr('Next lvl in:')
      SkillValueLabel

  HorizontalSeparator
    anchors.left: parent.left
    anchors.right: parent.right
    anchors.top: prev.bottom
    margin-top: 8
    margin-left: 10
    margin-right: 10
 
But you add this button on game_buttons?
I have no buttons added there

buttons.lua
Lua:
buttonsWindow = nil
contentsPanel = nil

function init()
  buttonsWindow = g_ui.loadUI('buttons', modules.game_interface.getRightPanel())
  buttonsWindow:disableResize()
  buttonsWindow:setup()
  contentsPanel = buttonsWindow.contentsPanel
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then
    buttonsWindow:close()
  end
end

function terminate()
  buttonsWindow:destroy()
end

function takeButtons(buttons)
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end
  for i, button in ipairs(buttons) do
    takeButton(button, true)
  end
  updateOrder()
end

function takeButton(button, dontUpdateOrder)
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end
  button:setParent(contentsPanel.buttons)
  if not dontUpdateOrder then
    updateOrder()
  end
end

function updateOrder()
   local children = contentsPanel.buttons:getChildren()
   table.sort(children, function(a, b)
    return (a.index or 1000) < (b.index or 1000)
   end)
   contentsPanel.buttons:reorderChildren(children)
   local visibleCount = 0
   for _, child in ipairs(children) do
    if child:isVisible() then
      visibleCount = visibleCount + 1
    end
   end
   if visibleCount > 6 and buttonsWindow:getHeight() < 30 then
    buttonsWindow:setHeight(buttonsWindow:getHeight() + 22)
   end
end

buttons.otui

Code:
GameButtonsWindow
  id: buttons
  &save: true
  !text: tr("Buttons")
  icon: /images/topbuttons/buttons
 
I have no buttons added there

buttons.lua
Lua:
buttonsWindow = nil
contentsPanel = nil

function init()
  buttonsWindow = g_ui.loadUI('buttons', modules.game_interface.getRightPanel())
  buttonsWindow:disableResize()
  buttonsWindow:setup()
  contentsPanel = buttonsWindow.contentsPanel
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then
    buttonsWindow:close()
  end
end

function terminate()
  buttonsWindow:destroy()
end

function takeButtons(buttons)
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end
  for i, button in ipairs(buttons) do
    takeButton(button, true)
  end
  updateOrder()
end

function takeButton(button, dontUpdateOrder)
  if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end
  button:setParent(contentsPanel.buttons)
  if not dontUpdateOrder then
    updateOrder()
  end
end

function updateOrder()
   local children = contentsPanel.buttons:getChildren()
   table.sort(children, function(a, b)
    return (a.index or 1000) < (b.index or 1000)
   end)
   contentsPanel.buttons:reorderChildren(children)
   local visibleCount = 0
   for _, child in ipairs(children) do
    if child:isVisible() then
      visibleCount = visibleCount + 1
    end
   end
   if visibleCount > 6 and buttonsWindow:getHeight() < 30 then
    buttonsWindow:setHeight(buttonsWindow:getHeight() + 22)
   end
end

buttons.otui

Code:
GameButtonsWindow
  id: buttons
  &save: true
  !text: tr("Buttons")
  icon: /images/topbuttons/buttons
show me your interface.otmod in game_interface
 
Tried to add game_exph in file, but give this error:
1657656128212.png
Follow file:

Code:
Module
  name: game_interface
  description: Create the game interface, where the ingame stuff starts
  author: OTClient team
  website: https://github.com/edubart/otclient
  sandboxed: true
  scripts: [ widgets/uigamemap, gameinterface ]
  load-later:
    - game_buttons
    - game_hotkeys
    - game_questlog
    - game_textmessage
    - game_console
    - game_outfit
    - game_healthinfo
    - game_skills
    - game_inventory
    - game_containers
    - game_viplist
    - game_battle
    - game_minimap
    - game_npctrade
    - game_textwindow
    - game_playertrade
    - game_bugreport
    - game_playerdeath
    - game_playermount
    - game_ruleviolation
    - game_market
    - game_spelllist
    - game_cooldown
    - game_modaldialog
    - game_unjustifiedpoints
    - game_walking
    - game_shop
    - game_itemselector
    - client_textedit
    - client_profiles
    - game_actionbar
    - game_prey
    - game_imbuing
    - game_stats
    - game_shaders
    - game_autolootz
  @onLoad: init()
  @onUnload: terminate()
 
Tried to add game_exph in file, but give this error:
View attachment 69237
Follow file:

Code:
Module
  name: game_interface
  description: Create the game interface, where the ingame stuff starts
  author: OTClient team
  website: https://github.com/edubart/otclient
  sandboxed: true
  scripts: [ widgets/uigamemap, gameinterface ]
  load-later:
    - game_buttons
    - game_hotkeys
    - game_questlog
    - game_textmessage
    - game_console
    - game_outfit
    - game_healthinfo
    - game_skills
    - game_inventory
    - game_containers
    - game_viplist
    - game_battle
    - game_minimap
    - game_npctrade
    - game_textwindow
    - game_playertrade
    - game_bugreport
    - game_playerdeath
    - game_playermount
    - game_ruleviolation
    - game_market
    - game_spelllist
    - game_cooldown
    - game_modaldialog
    - game_unjustifiedpoints
    - game_walking
    - game_shop
    - game_itemselector
    - client_textedit
    - client_profiles
    - game_actionbar
    - game_prey
    - game_imbuing
    - game_stats
    - game_shaders
    - game_autolootz
  @onLoad: init()
  @onUnload: terminate()
Fixed button issue, just changing image. How to put a reset button inside the analytics window?
 
Trying to put a reset button like this:
1657894590882.png
But gotting this error:
1657894555437.png
Button config:

exphButton
id: alRemoveList
margin-bottom: 3
margin-top: 5
height: 17
width: 80
text: Clean
@OnClick: modules.game_exph.resetExpH()
 
Back
Top