• 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!

Lua CandyBot Use Health Potion Faster

Devlinn

Member
Joined
Mar 25, 2015
Messages
295
Reaction score
6
hello i have problems to change time to next use potion
someone can little help?
i try change delay but dont work
Code:
-- Auto Healing Logic
SupportModule.AutoHeal = {}
AutoHeal = SupportModule.AutoHeal

local nextHeal = {}

local settings = {
  [RestoreType.cast] = 'AutoHeal',
  [RestoreType.item] = 'AutoHealthItem'
}

function AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, restoreType, tries)
  local tries = tries or 10

  local Panel = SupportModule.getPanel()
  if not Panel:getChildById(settings[restoreType]):isChecked() then
    return -- has since been unchecked
  end

  if restoreType == RestoreType.cast then
    local spellText = Panel:getChildById('HealSpellText'):getText()
    local healthValue = Panel:getChildById('HealthBar'):getValue()
   
    local delay = 0
    if player:getHealthPercent() < healthValue then
      g_game.talk(spellText)
      delay = Helper.getSpellDelay(spellText)
    end

    nextHeal[RestoreType.cast] = scheduleEvent(function()
      local player = g_game.getLocalPlayer()
      if not player then return end

      health, maxHealth = player:getHealth(), player:getMaxHealth()
      if player:getHealthPercent() < healthValue and tries > 0 then
        tries = tries - 1
        AutoHeal.onHealthChange(player, health, maxHealth, health, restoreType, tries)
      else
        removeEvent(nextHeal[RestoreType.cast])
      end
    end, delay)

  elseif restoreType == RestoreType.item then

    local item = Panel:getChildById('CurrentHealthItem'):getItem()
    if not item then
      Panel:getChildById('AutoHealthItem'):setChecked(false)
      return
    end

    local healthValue = Panel:getChildById('ItemHealthBar'):getValue()
    local delay = Helper.getItemUseDelay()

    if player:getHealthPercent() < healthValue then
      Helper.safeUseInventoryItemWith(item:getId(), player, BotModule.isPrecisionMode())
    end

    nextHeal[RestoreType.item] = scheduleEvent(function()
      local player = g_game.getLocalPlayer()
      if not player then return end
      health, maxHealth = player:getHealth(), player:getMaxHealth()
      if player:getHealthPercent() < healthValue and tries > 0 then
        tries = tries - 1
        AutoHeal.onHealthChange(player, health, maxHealth, health, restoreType, tries)
      else
        removeEvent(nextHeal[RestoreType.item])
      end
    end, delay)
  end
end

function AutoHeal.executeCast(player, health, maxHealth, oldHealth)
  AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, RestoreType.cast)
end

function AutoHeal.ConnectCastListener(listener)
  if g_game.isOnline() then
    local player = g_game.getLocalPlayer()
    addEvent(AutoHeal.onHealthChange(player, player:getHealth(),
      player:getMaxHealth(), player:getHealth(), RestoreType.cast))
  end

  connect(LocalPlayer, { onHealthChange = AutoHeal.executeCast })
end

function AutoHeal.DisconnectCastListener(listener)
  disconnect(LocalPlayer, { onHealthChange = AutoHeal.executeCast })
end

function AutoHeal.executeItem(player, health, maxHealth, oldHealth)
  AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, RestoreType.item)
end

function AutoHeal.ConnectItemListener(listener)
  if g_game.isOnline() then
    local player = g_game.getLocalPlayer()
    addEvent(AutoHeal.onHealthChange(player, player:getHealth(),
      player:getMaxHealth(), player:getHealth(), RestoreType.item))
  end

  connect(LocalPlayer, { onHealthChange = AutoHeal.executeItem })
end

function AutoHeal.DisconnectItemListener(listener)
  disconnect(LocalPlayer, { onHealthChange = AutoHeal.executeItem })
end
 
hello i have problems to change time to next use potion
someone can little help?
i try change delay but dont work
Code:
-- Auto Healing Logic
SupportModule.AutoHeal = {}
AutoHeal = SupportModule.AutoHeal

local nextHeal = {}

local settings = {
  [RestoreType.cast] = 'AutoHeal',
  [RestoreType.item] = 'AutoHealthItem'
}

function AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, restoreType, tries)
  local tries = tries or 10

  local Panel = SupportModule.getPanel()
  if not Panel:getChildById(settings[restoreType]):isChecked() then
    return -- has since been unchecked
  end

  if restoreType == RestoreType.cast then
    local spellText = Panel:getChildById('HealSpellText'):getText()
    local healthValue = Panel:getChildById('HealthBar'):getValue()
 
    local delay = 0
    if player:getHealthPercent() < healthValue then
      g_game.talk(spellText)
      delay = Helper.getSpellDelay(spellText)
    end

    nextHeal[RestoreType.cast] = scheduleEvent(function()
      local player = g_game.getLocalPlayer()
      if not player then return end

      health, maxHealth = player:getHealth(), player:getMaxHealth()
      if player:getHealthPercent() < healthValue and tries > 0 then
        tries = tries - 1
        AutoHeal.onHealthChange(player, health, maxHealth, health, restoreType, tries)
      else
        removeEvent(nextHeal[RestoreType.cast])
      end
    end, delay)

  elseif restoreType == RestoreType.item then

    local item = Panel:getChildById('CurrentHealthItem'):getItem()
    if not item then
      Panel:getChildById('AutoHealthItem'):setChecked(false)
      return
    end

    local healthValue = Panel:getChildById('ItemHealthBar'):getValue()
    local delay = Helper.getItemUseDelay()

    if player:getHealthPercent() < healthValue then
      Helper.safeUseInventoryItemWith(item:getId(), player, BotModule.isPrecisionMode())
    end

    nextHeal[RestoreType.item] = scheduleEvent(function()
      local player = g_game.getLocalPlayer()
      if not player then return end
      health, maxHealth = player:getHealth(), player:getMaxHealth()
      if player:getHealthPercent() < healthValue and tries > 0 then
        tries = tries - 1
        AutoHeal.onHealthChange(player, health, maxHealth, health, restoreType, tries)
      else
        removeEvent(nextHeal[RestoreType.item])
      end
    end, delay)
  end
end

function AutoHeal.executeCast(player, health, maxHealth, oldHealth)
  AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, RestoreType.cast)
end

function AutoHeal.ConnectCastListener(listener)
  if g_game.isOnline() then
    local player = g_game.getLocalPlayer()
    addEvent(AutoHeal.onHealthChange(player, player:getHealth(),
      player:getMaxHealth(), player:getHealth(), RestoreType.cast))
  end

  connect(LocalPlayer, { onHealthChange = AutoHeal.executeCast })
end

function AutoHeal.DisconnectCastListener(listener)
  disconnect(LocalPlayer, { onHealthChange = AutoHeal.executeCast })
end

function AutoHeal.executeItem(player, health, maxHealth, oldHealth)
  AutoHeal.onHealthChange(player, health, maxHealth, oldHealth, RestoreType.item)
end

function AutoHeal.ConnectItemListener(listener)
  if g_game.isOnline() then
    local player = g_game.getLocalPlayer()
    addEvent(AutoHeal.onHealthChange(player, player:getHealth(),
      player:getMaxHealth(), player:getHealth(), RestoreType.item))
  end

  connect(LocalPlayer, { onHealthChange = AutoHeal.executeItem })
end

function AutoHeal.DisconnectItemListener(listener)
  disconnect(LocalPlayer, { onHealthChange = AutoHeal.executeItem })
end

I checked both the source on github and your code and they are both identical
 
The item use delay that is called in candy bot, this on line 52
Code:
local delay = Helper.getItemUseDelay()
is defined in Helper on line 138
Code:
function Helper.getItemUseDelay()
  local ping = g_game.getPing()
  if ping < 1 then
  ping = 150
  end
  return Helper.safeDelay(ping + 200, ping + 400)
end
The safeDelay is defined on line 8 of Helper
Code:
function Helper.safeDelay(min, max)
  if g_game.isOfficialTibia() then
  return math.random(min, max)
  end
  return min
end

If you wanted to increase the speed you would need to set ping to 0 in the call to safeDelay inside of Helper.getItemUseDelay() because the clients ping value is being added to whatever value you are passing to it, ofcourse I have not checked the sources if there is base value set for delay between actions.

or Just set Helper.safeDelay(ping + 200, ping + 400) to Helper.safeDelay(1, 1) inside of Helper.getItemUseDelay()
 
The item use delay that is called in candy bot, this on line 52
Code:
local delay = Helper.getItemUseDelay()
is defined in Helper on line 138
Code:
function Helper.getItemUseDelay()
  local ping = g_game.getPing()
  if ping < 1 then
  ping = 150
  end
  return Helper.safeDelay(ping + 200, ping + 400)
end
The safeDelay is defined on line 8 of Helper
Code:
function Helper.safeDelay(min, max)
  if g_game.isOfficialTibia() then
  return math.random(min, max)
  end
  return min
end

If you wanted to increase the speed you would need to set ping to 0 in the call to safeDelay inside of Helper.getItemUseDelay() because the clients ping value is being added to whatever value you are passing to it, ofcourse I have not checked the sources if there is base value set for delay between actions.

or Just set Helper.safeDelay(ping + 200, ping + 400) to Helper.safeDelay(1, 1) inside of Helper.getItemUseDelay()
i change and now remove still dont work ;]
Code:
--[[
  @Authors: Ben Dol (BeniS)
  @Details: Helper methods for global use.
]]

Helper = {}

function Helper.safeDelay(min, min)
  if g_game.isOfficialTibia() then
    return math.random(min, max)
  end
  return min
end

function Helper.safeUseInventoryItem(itemId, forceCheck)
  if forceCheck or g_game.isOfficialTibia() then
    local player = g_game.getLocalPlayer()
    if player:getItemsCount(itemId) < 1 then
      return false
    end
  end

  if g_game.getProtocolVersion() < 800 then -- Need to verify
    local item = g_game.findPlayerItem(itemId, -1)
    if item then
      if item:getSubType() > 1 then
        g_game.use(item, thing)
      else
        g_game.useInventoryItem(itemId, thing)
      end
      return true
    end
    return false
  end

  g_game.useInventoryItem(itemId)
  return true
end

function Helper.safeUseInventoryItemWith(itemId, thing, forceCheck)
  if forceCheck or g_game.isOfficialTibia() then
    local player = g_game.getLocalPlayer()
    if player:getItemsCount(itemId) < 1 then
      return false
    end
  end

  if g_game.getProtocolVersion() < 800 then -- Need to verify
    local item = g_game.findPlayerItem(itemId, -1)
    if item then
      if item:getSubType() > 1 then
        g_game.useWith(item, thing)
      else
        g_game.useInventoryItemWith(itemId, thing)
      end
      return true
    end
    return false
  end

  g_game.useInventoryItemWith(itemId, thing)
  return true
end

function Helper.castSpell(player, words, defaultGroupId)
  local spell = nil
  if BotModule.isPrecisionMode() then
    spell = Spells.getSpellByWords(words)
  end

  if defaultGroupId then
    local groupCooldown = modules.game_cooldown.isGroupCooldownIconActive(defaultGroupId)
    if groupCooldown then
      BotLogger.debug(SpellGroups[defaultGroupId].." group cooldown is active.")
      return false
    end
  end

  local playerId = player:getId()
  if spell then
    local iconId = spell.id

    local cooldown = modules.game_cooldown.isCooldownIconActive(iconId)
    if cooldown then
      BotLogger.debug("Group "..SpellGroups[iconId].." cooldown is active")
      return false
    end

    for groupId,_ in pairs(spell.group) do
      local groupCooldown = modules.game_cooldown.isGroupCooldownIconActive(groupId)
      if groupCooldown then
        BotLogger.debug("Group "..SpellGroups[groupId].." cooldown is active")
        return false
      end
    end

    if player:getSoul() < spell.soul then
      BotLogger.warning("Not enough soul points("..spell.soul..") to cast this spell.")
      return false
    end

    if Helper.hasEnoughMana(player, spell) then
      g_game.talk(spell.words)
    end
  else
    if player:getMana() > 0 then
      g_game.talk(words)
    end
  end
  return true
end

function Helper.hasEnoughMana(player, spell)
  if type(spell) ~= "table" then
    spell = Spells.getSpellByWords(spell)
  end
  if spell then
    return player:getMana() >= spell.mana
  end
  return player:getMana() > 0
end

function Helper.getSpellDelay(words)
  local delay = 0
  local ping = g_game.getPing()
  if ping < 1 then ping = 150 end

  delay = ping * 2 -- default delay
  if BotModule.isPrecisionMode() then
    local spell = Spells.getSpellByWords(words)
    if spell then
      delay = spell.exhaustion + (ping / 3)
    end
  end
  return Helper.safeDelay(delay, delay + 200)
end

function Helper.getItemUseDelay()
Helper.safeDelay(1, 1)
end

function Helper.getRandomVocationSpell(vocId, groups)
  local vocSpells = Spells.getSpellsByVocationId(vocId)
  local spells = Spells.filterSpellsByGroups(vocSpells, groups)
  return not table.empty(spells) and spells[math.random(1,#spells)] or {}
end

function Helper.startChooseItem(releaseCallback)
  if not releaseCallback then
    error("No mouse release callback parameter set.")
  end
  local mouseGrabberWidget = g_ui.createWidget('UIWidget')
  mouseGrabberWidget:setVisible(false)
  mouseGrabberWidget:setFocusable(false)

  connect(mouseGrabberWidget, { onMouseRelease = function(self, mousePosition, mouseButton)
    local item = nil
    if mouseButton == MouseLeftButton then
      local clickedWidget = modules.game_interface.getRootPanel()
        :recursiveGetChildByPos(mousePosition, false)
   
      if clickedWidget then
        if clickedWidget:getClassName() == 'UIMap' then
          local tile = clickedWidget:getTile(mousePosition)
         
          if tile then
            local thing = tile:getTopMoveThing()
            if thing then
              item = thing:asItem()
            end
          end
         
        elseif clickedWidget:getClassName() == 'UIItem' and not clickedWidget:isVirtual() then
          item = clickedWidget:getItem()
        end
      end
    end
   
    if releaseCallback(self, item) then
      -- revert mouse change
      g_mouse.popCursor()
      self:ungrabMouse()
      self:destroy()
    end
  end })
 
  mouseGrabberWidget:grabMouse()
  g_mouse.pushCursor('target')

  CandyBot.hide()
end

function Helper.getActiveRingId(itemid)
  return RingIds[itemid]
end

function Helper.getRingIdByName(name)
  return Rings[name]
end

function Helper.getItemFromTiles(tiles, itemId)
  local items = {}
 
  for _,tile in pairs(tiles) do
    if tile and tile:getThing() then
      if table.contains(itemId, tile:getThing():getId()) then
        table.insert(items, tile)
      end
    end
  end
  return items
end
 
When you call a function for example, if you wanted to add 2 numbers to together
Code:
a = 1
b = 2
You could write a function to do this
Code:
function add(x, y)
    return x + y
end
Now that you have a function that is defined, you call it (use it)
Code:
add(a, b) -- returns 3
If the add function didn't have a return statement then when you called the add function it wouldn't do anything for the numbers you passed to it.

Please note a return statement isn't always needed, but in this case with the add function it is.

You really need to learn lua, it is essential in order for you to write / edit scripts
--------------------------------------------------------
@topic
In your code here you are calling Helper.safeDelay twice which is pointless, you only need to call it once, if the function your calling returns a value you can just return it.
Code:
function Helper.getItemUseDelay()
    return Helper.safeDelay(1, 1)
end
 
Last edited:
When you call a function for example, if you wanted to add 2 numbers to together
Code:
a = 1
b = 2
You could write a function to do this
Code:
function add(x, y)
    return x + y
end
Now that you have a function that is defined, you call it (use it)
Code:
add(a, b) -- returns 3
If the add function didn't have a return statement then when you called the add function it wouldn't do anything for the numbers you passed to it.

You really need to learn lua, it is essential in order for you to write / edit scripts
--------------------------------------------------------
@topic
In your code here you are calling Helper.delay twice which is pointless, you only need to call it once, if the function your calling returns a value you can just return it.
Code:
function Helper.getItemUseDelay()
    return Helper.safeDelay(1, 1)
end
ok
this too dont work ;]
Code:
function Helper.getItemUseDelay()
    return Helper.safeDelay(1, 1)
end
 
:( Must be a default set somewhere.. i can't test it because I don't use the custom client.
maybe here?
Code:
--[[
  @Authors: Ben Dol (BeniS)
  @Details: MoveProcedure class for auto moving things.
]]
if not Procedure then
  dofile("procedure.lua")
end

MoveProcedure = extends(Procedure, "MoveProcedure")

MoveProcedure.create = function(thing, position, verify, timeoutTicks)
  local proc = MoveProcedure.internalCreate()

  proc:setId(thing)

  if not Position.isValid(position) then
    perror(debug.traceback("position is not valid"))
  end
  proc.position = position

  print(proc:getTickoutTicks())
  if timeoutTicks then
    print(timeoutTicks)
    proc:setTimeoutTicks(timeoutTicks)
  end
  proc.tryMoveEvent = nil
  proc.verify = verify

  if thing then
    local class = thing:getClassName()
    if type(thing) ~= "userdata" then
      perror(debug.traceback("thing provided is not userdata"))
    elseif class ~= "Creature" and class ~= "Item" then
      perror(debug.traceback("thing provided must be a Creature or Item class"))
    end
    proc.thing = thing
  else
    perror(debug.traceback("thing cannot be nil"))
  end
  return proc
end

-- gets/sets

function MoveProcedure:getThing()
  return self.thing
end

function MoveProcedure:setThing(thing)
  self.thing = thing
end

function MoveProcedure:getPosition()
  return self.position
end

function MoveProcedure:setPosition(position)
  self.position = position
end

-- logic

function MoveProcedure:start()
  print("MoveProcedure:start")
  Procedure.start(self)

  -- try move thing
  scheduleEvent(function() self:tryMove() end, Helper.safeDelay(800, 1200))

  signalcall(self.onStarted, self.id)
end

-- TODO: This needs to be reworked
function MoveProcedure:tryMove()
  self:stopTryMove()
 
  if self:isTimedOut() then return end
  g_game.move(self.thing, self.position, self.thing:getCount())
 
  -- the move has been called schedule finish
  local wait = (g_game.getPing()*1.5)
  if wait > 0 then
    self.tryMoveEvent = scheduleEvent(function()
      if self:isTimedOut() then return end

      -- TODO: Fix verification
      if not self.verify or self:verifyMoved() then
        self:finish()
      else
        self:tryMove()
      end
    end, wait)
  else
    self:finish()
  end
end

function MoveProcedure:verifyMoved()
  print("MoveProcedure:verifyMoved()")
  return true
end

function MoveProcedure:stopTryMove()
  if self.tryMoveEvent then
    self.tryMoveEvent:cancel()
    self.tryMoveEvent = nil
  end
end

function MoveProcedure:stop()
  Procedure.stop(self)
  print("MoveProcedure:stop()")

  self:clean()

  signalcall(self.onStopped, self.id)
end

function MoveProcedure:cancel()
  Procedure.cancel(self)
  print("MoveProcedure:cancel()")

  self:clean()

  signalcall(self.onCancelled, self.id)
end

function MoveProcedure:fail()
  Procedure.fail(self)
  print("MoveProcedure:fail()")

  self:clean()

  signalcall(self.onFailed, self.id)
end

function MoveProcedure:timeout()
  Procedure.timeout(self)
  print("MoveProcedure:timeout()")

  self:clean()

  signalcall(self.onTimedOut, self.id)
end

function MoveProcedure:finish()
  Procedure.finish(self)
  print("MoveProcedure:finish()")

  self:clean()

  signalcall(self.onFinished, self.id)
end

function MoveProcedure:clean()
  Procedure.clean(self)
  print("MoveProcedure:clean()")

  self:stopTryMove()

  signalcall(self.onCleaned, self.id)
end
 
The client can't always override the server especially not between actions, there are default values set somewhere in the source to prevent this & that is what your trying to accomplish here.

And MoveProcedure has nothing to do with using an item.
Your doing what they call reaching :p
 
The client can't always override the server especially not between actions, there are default values set somewhere in the source to prevent this & that is what your trying to accomplish here.

And MoveProcedure has nothing to do with using an item.
Your doing what they call reaching :p
so i need find it on source otclient?

edit i find on source only this
Code:
Game::Game()
{
    m_protocolVersion = 0;
    m_clientCustomOs = -1;
    m_clientVersion = 0;
    m_online = false;
    m_denyBotCall = false;
    m_dead = false;
    m_serverBeat = 50;
    m_seq = 0;
    m_ping = -1;
    m_pingDelay = 1000;                   //here
    m_canReportBugs = false;
    m_fightMode = Otc::FightBalanced;
    m_chaseMode = Otc::DontChase;
    m_pvpMode = Otc::WhiteDove;
    m_safeFight = true;
}
 
Back
Top