Updated to OTCv8 3.0 rev 99

This commit is contained in:
OTCv8 2021-09-05 16:09:55 +00:00
parent a22d7a7a63
commit 4231b74314
96 changed files with 3024 additions and 1713 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,401 +0,0 @@
AttackEntry < Label
background-color: alpha
text-offset: 18 0
focusable: true
height: 16
CheckBox
id: enabled
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 15
height: 15
margin-top: 2
margin-left: 3
$focus:
background-color: #00000055
Button
id: remove
!text: tr('x')
anchors.right: parent.right
margin-right: 15
width: 15
height: 15
AttackWindow < MainWindow
!text: tr('AttackBot')
size: 800 350
TextList
id: attackList
anchors.left: parent.left
anchors.top: parent.top
padding: 1
size: 500 150
margin-left: 3
margin-top: 3
margin-left: 3
vertical-scrollbar: attackListScrollBar
VerticalScrollBar
id: attackListScrollBar
anchors.top: attackList.top
anchors.bottom: attackList.bottom
anchors.right: attackList.right
step: 14
pixels-scroll: true
Label
id: category
anchors.top: attackList.bottom
anchors.left: attackList.left
anchors.right: attackList.right
text-align: center
margin-top: 5
image-source: /images/ui/panel_flat
image-border: 5
height: 21
margin-left: 25
margin-right: 25
NextButton
id: categoryNext
anchors.left: category.right
anchors.verticalCenter: category.verticalCenter
margin-left: 10
PreviousButton
id: categoryPrev
anchors.right: category.left
anchors.verticalCenter: category.verticalCenter
margin-right: 10
Label
id: parameter1
anchors.top: category.bottom
anchors.left: category.left
anchors.right: category.horizontalCenter
margin-top: 5
margin-right: 25
height: 21
text-align: center
image-source: /images/ui/panel_flat
image-border: 5
NextButton
id: parameter1Next
anchors.left: parameter1.right
anchors.verticalCenter: parameter1.verticalCenter
margin-left: 10
PreviousButton
id: parameter1Prev
anchors.right: parameter1.left
anchors.verticalCenter: parameter1.verticalCenter
margin-right: 10
Label
id: parameter2
anchors.top: category.bottom
anchors.left: category.horizontalCenter
anchors.right: category.right
margin-top: 5
margin-left: 25
height: 21
text-align: center
image-source: /images/ui/panel_flat
image-border: 5
NextButton
id: parameter2Next
anchors.left: parameter2.right
anchors.verticalCenter: parameter2.verticalCenter
margin-left: 10
PreviousButton
id: parameter2Prev
anchors.right: parameter2.left
anchors.verticalCenter: parameter2.verticalCenter
margin-right: 10
TextEdit
id: spellFormula
anchors.left: parent.left
anchors.top: parameter2Prev.bottom
margin-top: 20
margin-left: 30
width: 200
Label
id: spellDescription
anchors.left: prev.left
anchors.right: prev.right
anchors.bottom: prev.top
margin-bottom: 2
text-align: center
text: Insert Spell Formula Below
BotItem
id: itemId
anchors.left: parent.left
anchors.top: parameter2Prev.bottom
margin-top: 10
margin-left: 20
Label
id: itemDescription
anchors.left: itemId.right
margin-left: 5
anchors.verticalCenter: itemId.verticalCenter
text: < insert id or drag item here
Label
anchors.left: parent.left
anchors.bottom: BottomSeparator.top
margin-bottom: 10
text-align: center
text: Min Monsters:
SpinBox
id: minMonsters
anchors.left: prev.right
anchors.verticalCenter: prev.verticalCenter
margin-left: 5
width: 45
minimum: 1
maximum: 100
focusable: true
Label
anchors.left: minMonsters.right
anchors.verticalCenter: minMonsters.verticalCenter
margin-left: 10
text-align: center
text: Min Mana%:
SpinBox
id: minMana
anchors.left: prev.right
anchors.verticalCenter: prev.verticalCenter
margin-left: 5
width: 45
minimum: 1
maximum: 100
focusable: true
Label
anchors.left: prev.right
anchors.verticalCenter: prev.verticalCenter
margin-left: 10
text: Cooldown(ms):
!tooltip: tr('Optional, can be left at 1, recommended for custom spells/old tibia')
SpinBox
id: newCooldown
anchors.left: prev.right
anchors.verticalCenter: prev.verticalCenter
margin-left: 5
width: 60
minimum: 0
maximum: 99999
focusable: true
CheckBox
id: pvpSpell
anchors.verticalCenter: spellFormula.verticalCenter
anchors.left: spellFormula.right
width: 100
margin-left: 50
text: Spell for PVP
Button
id: addButton
anchors.right: attackList.right
anchors.bottom: BottomSeparator.top
text-align: center
text: Add
margin-bottom: 10
size: 80 20
Button
id: MoveUp
anchors.right: prev.right
anchors.bottom: prev.top
size: 80 20
text: Move Up
margin-bottom: 2
Button
id: MoveDown
anchors.right: prev.right
anchors.bottom: prev.top
size: 80 20
text: Move Down
text-align: center
margin-bottom: 2
VerticalSeparator
anchors.top: parent.top
anchors.bottom: BottomSeparator.top
anchors.left: MoveDown.right
margin-top: 3
margin-bottom: 3
margin-left: 10
Label
id: thing
anchors.left: prev.right
anchors.right: parent.right
anchors.top: parent.top
margin-top: 3
text-align: center
text: Additional Options
HorizontalSeparator
anchors.left: prev.left
anchors.right: prev.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 5
CheckBox
id: IgnoreMana
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 10
margin-left: 5
width: 200
text: Check RL Tibia conditions
CheckBox
id: Kills
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 200
height: 22
text: Don't use area attacks if less than kills to red skull
text-wrap: true
text-align: left
SpinBox
id: KillsAmount
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.left: prev.right
text-align: center
width: 50
minimum: 1
maximum: 10
focusable: true
margin-left: 5
Label
anchors.left: Kills.left
anchors.bottom: BottomSeparator.top
margin-bottom: 8
text: Profile:
TextEdit
id: Name
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 5
Button
id: ResetSettings
anchors.verticalCenter: prev.verticalCenter
anchors.right: parent.right
text: Reset Settings
margin-top: 1
CheckBox
id: Rotate
anchors.top: Kills.bottom
anchors.left: Kills.left
margin-top: 8
width: 220
text: Turn to side with most monsters
CheckBox
id: Cooldown
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 220
text: Check spell cooldowns
CheckBox
id: Visible
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: Items must be visible (recommended)
CheckBox
id: PvpMode
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: PVP mode
CheckBox
id: PvpSafe
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: PVP safe
CheckBox
id: BlackListSafe
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 200
height: 18
text: Stop if Anti-RS player in range
SpinBox
id: AntiRsRange
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.left: prev.right
text-align: center
width: 50
minimum: 1
maximum: 10
focusable: true
margin-left: 5
Label
anchors.left: thing.left
anchors.right: thing.right
anchors.bottom: ResetSettings.top
margin-bottom: 10
text: Note: Cooldown value is optional for new global Tibia, recommended for Old tibia and custom OT
text-wrap: true
text-align: center
height: 40
multiline: true
HorizontalSeparator
id: BottomSeparator
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: CloseButton.top
margin-bottom: 8
Button
id: CloseButton
!text: tr('Close')
font: cipsoftFont
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
margin-right: 5

View File

@ -17,6 +17,7 @@ end
-- libraries should be loaded first -- libraries should be loaded first
local luaFiles = { local luaFiles = {
"main", "main",
"items",
"vlib", "vlib",
"new_cavebot_lib", "new_cavebot_lib",
"configs", -- do not change this and above "configs", -- do not change this and above
@ -42,7 +43,7 @@ local luaFiles = {
"eat_food", "eat_food",
"equip", "equip",
"exeta", "exeta",
"info", "analyzer",
"jewellery_equipper", "jewellery_equipper",
"spy_level", "spy_level",
"supplies", "supplies",

View File

@ -1,5 +1,7 @@
CaveBot.Actions = {} CaveBot.Actions = {}
local antiTrapTriggered = false
-- it adds an action widget to list -- it adds an action widget to list
CaveBot.addAction = function(action, value, focus) CaveBot.addAction = function(action, value, focus)
action = action:lower() action = action:lower()
@ -148,7 +150,9 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
return false -- different floor return false -- different floor
end end
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > 40 then local maxDist = storage.extras.gotoMaxDistance or 40
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then
return false -- too far way return false -- too far way
end end
@ -163,34 +167,36 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
return true -- already at position return true -- already at position
end end
-- check if there's a path to that place, ignore creatures and fields -- check if there's a path to that place, ignore creatures and fields
local path = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true }) local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
if not path then if not path then
return false -- there's no way return false -- there's no way
end end
-- check if there's a path to destination but consider Creatures (attack only if trapped) -- check if there's a path to destination but consider Creatures (attack only if trapped)
local path2 = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1 }) local path2 = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1 })
if not path2 then if not path2 then
local monsters = {} local target = {} -- c = creature, d = distance
for i, spec in pairs(getSpectators()) do for i, spec in pairs(getSpectators()) do
if spec:isMonster() and spec:getType() ~= 3 then if spec:isMonster() then
if spec:canShoot() and findPath(playerPos, spec:getPosition(), 20, {ignoreNonPathable = true, precision = 1}) then local path = findPath(playerPos, spec:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
table.insert(monsters, {mob = spec, dist = getDistanceBetween(pos, spec:getPosition())}) if path then
local dist = getDistanceBetween(pos, spec:getPosition())
if not target.d or target.d > dist then
target = {c=spec, d=dist}
end
end end
end end
end end
table.sort(monsters, function(a,b) return a.dist < b.dist end) if target.c then
if monsters[1] then if target.c ~= getTarget() then
g_game.attack(monsters[1].mob) attack(target.c)
storage.blockMonster = monsters[1].mob end
autoWalk(storage.blockMonster, 10, {precision = 1})
storage.clearing = true
CaveBot.setOff()
g_game.setChaseMode(1) g_game.setChaseMode(1)
schedule(3000, function() CaveBot.setOn() end) -- just in case callback trigger fails CaveBot.setOff()
antiTrapTriggered = true
return "retry" return "retry"
else else
return false -- there's no way return false -- no other way
end end
end end
@ -200,7 +206,7 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
end end
-- try to find path, don't ignore creatures, ignore fields -- try to find path, don't ignore creatures, ignore fields
if CaveBot.walkTo(pos, 40, { ignoreNonPathable = true }) then if CaveBot.walkTo(pos, maxDist, { ignoreNonPathable = true }) then
return "retry" return "retry"
end end
@ -224,34 +230,14 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
end end
-- everything else failed, try to walk ignoring creatures, maybe will work -- everything else failed, try to walk ignoring creatures, maybe will work
CaveBot.walkTo(pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true }) CaveBot.walkTo(pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
return "retry" return "retry"
end) end)
onCreatureDisappear(function(creature) onAttackingCreatureChange(function(creature, oldCreature)
if creature ~= storage.blockMonster then return end if antiTrapTriggered then
if storage.clearing then
CaveBot.setOn() CaveBot.setOn()
storage.blockMonster = nil antiTrapTriggered = false
storage.clearing = false
end
end)
onCreaturePositionChange(function(creature, newPos, oldPos)
if creature ~= storage.blockMonster and creature ~= player then return end
if storage.clearing then
if creature == storage.blockMonster and not findPath(player:getPosition(), newPos, 20, {ignoreNonPathable = true, precision = 1}) then
CaveBot.setOn()
storage.blockMonster = nil
storage.clearing = false
end
if creature == player then
if oldPos.z ~= newPos.z then
CaveBot.setOn()
storage.blockMonster = nil
storage.clearing = false
end
end
end end
end) end)

View File

@ -10,6 +10,7 @@ CaveBot.Extensions.DWithdraw.setup = function()
end end
local destContainer local destContainer
local depotContainer local depotContainer
delay(70)
-- input validation -- input validation
if not value or #data ~= 3 and #data ~= 4 then if not value or #data ~= 3 and #data ~= 4 then
@ -25,6 +26,11 @@ CaveBot.Extensions.DWithdraw.setup = function()
-- cap check -- cap check
if freecap() < (capLimit or 200) then if freecap() < (capLimit or 200) then
for i, container in ipairs(getContainers()) do
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
g_game.close(container)
end
end
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding") print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
return true return true
end end
@ -56,6 +62,7 @@ CaveBot.Extensions.DWithdraw.setup = function()
-- stash validation -- stash validation
if depotContainer and #depotContainer:getItems() == 0 then if depotContainer and #depotContainer:getItems() == 0 then
print("CaveBot[DepotWithdraw]: all items withdrawn") print("CaveBot[DepotWithdraw]: all items withdrawn")
g_game.close(depotContainer)
return true return true
end end
@ -79,6 +86,7 @@ CaveBot.Extensions.DWithdraw.setup = function()
for i, container in pairs(g_game.getContainers()) do for i, container in pairs(g_game.getContainers()) do
if string.find(container:getName():lower(), "depot box") then if string.find(container:getName():lower(), "depot box") then
for j, item in ipairs(container:getItems()) do for j, item in ipairs(container:getItems()) do
statusMessage("[D_Withdraw] witdhrawing item: "..item:getId())
g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount()) g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount())
return "retry" return "retry"
end end

View File

@ -11,6 +11,12 @@ local function resetCache()
reopenedContainers = false reopenedContainers = false
destination = nil destination = nil
lootTable = nil lootTable = nil
for i, container in ipairs(getContainers()) do
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
g_game.close(container)
end
end
end end
local description = g_game.getClientVersion() > 960 and "No - just deposit \n Yes - also reopen loot containers" or "currently not supported, will be added in near future" local description = g_game.getClientVersion() > 960 and "No - just deposit \n Yes - also reopen loot containers" or "currently not supported, will be added in near future"
@ -31,6 +37,8 @@ CaveBot.Extensions.Depositor.setup = function()
return true return true
end end
delay(70)
-- backpacks etc -- backpacks etc
if value:lower() == "yes" then if value:lower() == "yes" then
-- reopening backpacks -- reopening backpacks
@ -106,6 +114,7 @@ CaveBot.Extensions.Depositor.setup = function()
local id = item:getId() local id = item:getId()
if table.find(lootTable, id) then if table.find(lootTable, id) then
local index = getStashingIndex(id) or item:isStackable() and 1 or 0 local index = getStashingIndex(id) or item:isStackable() and 1 or 0
statusMessage("[Depositer] stashing item: " ..id.. " to depot: "..index+1)
CaveBot.StashItem(item, index, destination) CaveBot.StashItem(item, index, destination)
return "retry" return "retry"
end end

View File

@ -46,6 +46,7 @@ CaveBot.Extensions.InWithdraw.setup = function()
end end
if inboxAmount == 0 then if inboxAmount == 0 then
warn("CaveBot[InboxWithdraw]: not enough items in inbox container, proceeding") warn("CaveBot[InboxWithdraw]: not enough items in inbox container, proceeding")
g_game.close(inboxContainer)
return true return true
end end
@ -58,7 +59,8 @@ CaveBot.Extensions.InWithdraw.setup = function()
if not destination then if not destination then
print("CaveBot[InboxWithdraw]: couldn't find proper destination container, skipping") print("CaveBot[InboxWithdraw]: couldn't find proper destination container, skipping")
return falsed g_game.close(inboxContainer)
return false
end end
CaveBot.PingDelay(2) CaveBot.PingDelay(2)

View File

@ -0,0 +1,26 @@
local minimap = modules.game_minimap.minimapWidget
minimap.onMouseRelease = function(widget,pos,button)
if not minimap.allowNextRelease then return true end
minimap.allowNextRelease = false
local mapPos = minimap:getTilePosition(pos)
if not mapPos then return end
if button == 1 then
local player = g_game.getLocalPlayer()
if minimap.autowalk then
player:autoWalk(mapPos)
end
return true
elseif button == 2 then
local menu = g_ui.createWidget('PopupMenu')
menu:setId("minimapMenu")
menu:setGameMenu(true)
menu:addOption(tr('Create mark'), function() minimap:createFlagWindow(mapPos) end)
menu:addOption(tr('Add CaveBot GoTo'), function() CaveBot.addAction("goto", mapPos.x .. "," .. mapPos.y .. "," .. mapPos.z, true) CaveBot.save() end)
menu:display(pos)
return true
end
return false
end

View File

@ -172,7 +172,7 @@ onTextMessage(function(mode, text)
local m1 = storage.caveBotTasker.monster local m1 = storage.caveBotTasker.monster
local m2 = storage.caveBotTasker.monster2 local m2 = storage.caveBotTasker.monster2
if monster == m1 or monster == m2 and storage.caveBotTasker.countaa then if monster == m1 or monster == m2 and storage.caveBotTasker.count then
storage.caveBotTasker.count = storage.caveBotTasker.count + 1 storage.caveBotTasker.count = storage.caveBotTasker.count + 1
end end
end) end)

View File

@ -23,15 +23,26 @@ CaveBot.Extensions.Withdraw.setup = function()
-- check for retries -- check for retries
if retries > 100 then if retries > 100 then
print("CaveBot[Withdraw]: actions limit reached, proceeding") print("CaveBot[Withdraw]: actions limit reached, proceeding")
for i, container in ipairs(getContainers()) do
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
g_game.close(container)
end
end
return true return true
end end
-- check for items -- check for items
if itemAmount(id) >= amount then if itemAmount(id) >= amount then
print("CaveBot[Withdraw]: enough items, proceeding") print("CaveBot[Withdraw]: enough items, proceeding")
for i, container in ipairs(getContainers()) do
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
g_game.close(container)
end
end
return true return true
end end
statusMessage("[Withdraw] withdrawing item: " ..id.. " x"..amount)
CaveBot.WithdrawItem(id, amount, source) CaveBot.WithdrawItem(id, amount, source)
CaveBot.PingDelay() CaveBot.PingDelay()
return "retry" return "retry"

View File

@ -3,6 +3,49 @@ local targetCount = 0
local delayValue = 0 local delayValue = 0
local lureMax = 0 local lureMax = 0
local anchorPosition = nil local anchorPosition = nil
local lastCall = now
local delayFrom = nil
function getWalkableTilesCount(position)
local count = 0
for i, tile in pairs(getNearTiles(position)) do
if tile:isWalkable() or tile:hasCreature() then
count = count + 1
end
end
return count
end
function rePosition(minTiles)
minTiles = minTiles or 8
if now - lastCall < 500 then return end
local pPos = player:getPosition()
local tiles = getNearTiles(pPos)
local playerTilesCount = getWalkableTilesCount(pPos)
local tilesTable = {}
if playerTilesCount > minTiles then return end
for i, tile in ipairs(tiles) do
tilesTable[tile] = not tile:hasCreature() and tile:isWalkable() and getWalkableTilesCount(tile:getPosition()) or nil
end
local best = 0
local target = nil
for k,v in pairs(tilesTable) do
if v > best and v > playerTilesCount then
best = v
target = k:getPosition()
end
end
if target then
lastCall = now
return CaveBot.GoTo(target, 0)
end
end
TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority} TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority}
if player:isWalking() then if player:isWalking() then
lastWalk = now lastWalk = now
@ -97,9 +140,10 @@ TargetBot.Creature.walk = function(creature, config, targets)
lureMax = config.lureMax lureMax = config.lureMax
end end
delayFrom = config.delayFrom
-- luring -- luring
if TargetBot.canLure() and (config.lure or config.lureCavebot or config.dynamicLure) and not (config.chase and creature:getHealthPercent() < 5) and not isTrapped then if TargetBot.canLure() and (config.lure or config.lureCavebot or config.dynamicLure) and not (creature:getHealthPercent() < (storage.extras.killUnder or 30)) and not isTrapped then
local monsters = 0 local monsters = 0
if targetBotLure then if targetBotLure then
anchorPosition = nil anchorPosition = nil
@ -119,8 +163,12 @@ TargetBot.Creature.walk = function(creature, config, targets)
end end
end end
local lastRePosition = now
if not config.chase and not config.keepDistance and config.rePosition and (creature:getHealthPercent() >= storage.extras.killUnder) then
return rePosition(config.rePositionAmount or 6)
end
local currentDistance = findPath(pos, cpos, 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true}) local currentDistance = findPath(pos, cpos, 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true})
if config.chase and (creature:getHealthPercent() < (storage.extras.killUnder or 30) or not config.keepDistance) then if ((storage.extras.killUnder > 1 and (creature:getHealthPercent() < storage.extras.killUnder)) or config.chase) and not config.keepDistance then
if #currentDistance > 1 then if #currentDistance > 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1}) return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1})
end end
@ -187,6 +235,6 @@ onPlayerPositionChange(function(newPos, oldPos)
if not lureMax then return end if not lureMax then return end
if storage.TargetBotDelayWhenPlayer then return end if storage.TargetBotDelayWhenPlayer then return end
if targetCount < lureMax/2 or not target() then return end if targetCount < (delayFrom or lureMax/2) or not target() then return end
CaveBot.delay(delayValue or 0) CaveBot.delay(delayValue or 0)
end) end)

View File

@ -82,9 +82,11 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
addScrollBar("keepDistanceRange", "Keep distance", 1, 5, 1) addScrollBar("keepDistanceRange", "Keep distance", 1, 5, 1)
addScrollBar("anchorRange", "Anchoring Range", 1, 10, 3) addScrollBar("anchorRange", "Anchoring Range", 1, 10, 3)
addScrollBar("lureCount", "Classic Lure", 0, 5, 1) addScrollBar("lureCount", "Classic Lure", 0, 5, 1)
addScrollBar("lureMin", "Dynamic lure min", 0, 9, 1) addScrollBar("lureMin", "Dynamic lure min", 0, 29, 1)
addScrollBar("lureMax", "Dynamic lure max", 1, 9, 3) addScrollBar("lureMax", "Dynamic lure max", 1, 30, 3)
addScrollBar("lureDelay", "Dynamic lure delay", 100, 1000, 250) addScrollBar("lureDelay", "Dynamic lure delay", 100, 1000, 250)
addScrollBar("delayFrom", "Start delay when monsters", 1, 29, 2)
addScrollBar("rePositionAmount", "Min tiles to rePosition", 0, 7, 5)
addCheckBox("chase", "Chase", true) addCheckBox("chase", "Chase", true)
addCheckBox("keepDistance", "Keep Distance", false) addCheckBox("keepDistance", "Keep Distance", false)
@ -97,4 +99,5 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
addCheckBox("dynamicLure", "Dynamic lure", false) addCheckBox("dynamicLure", "Dynamic lure", false)
addCheckBox("dynamicLureDelay", "Dynamic lure delay", false) addCheckBox("dynamicLureDelay", "Dynamic lure delay", false)
addCheckBox("diamondArrows", "D-Arrows priority", false) addCheckBox("diamondArrows", "D-Arrows priority", false)
addCheckBox("rePosition", "rePosition to better tile", false)
end end

View File

@ -166,7 +166,7 @@ TargetBot.Looting.getLootContainers = function(containers)
for index, container in pairs(containers) do for index, container in pairs(containers) do
openedContainersById[container:getContainerItem():getId()] = 1 openedContainersById[container:getContainerItem():getId()] = 1
if containersById[container:getContainerItem():getId()] and not container.lootContainer then if containersById[container:getContainerItem():getId()] and not container.lootContainer then
if container:getItemsCount() < container:getCapacity() then if container:getItemsCount() < container:getCapacity() or container:hasPages() then
table.insert(lootContainers, container) table.insert(lootContainers, container)
else -- it's full, open next container if possible else -- it's full, open next container if possible
for slot, item in ipairs(container:getItems()) do for slot, item in ipairs(container:getItems()) do

View File

@ -67,17 +67,3 @@ TargetBotLootingPanel < Panel
anchors.verticalCenter: prev.verticalCenter anchors.verticalCenter: prev.verticalCenter
text: Min. capacity: text: Min. capacity:
margin-left: 5 margin-left: 5
Label
margin-top: 3
margin-left: 20
margin-right: 20
!text: tr("Drag item or click on any of empty slot")
text-align: center
text-wrap: true
text-auto-resize: true
BotButton
margin-top: 3
text: Help & Tutorials
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")

View File

@ -47,7 +47,7 @@ targetbotMacro = macro(100, function()
local targets = 0 local targets = 0
local highestPriorityParams = nil local highestPriorityParams = nil
for i, creature in ipairs(creatures) do for i, creature in ipairs(creatures) do
local path = findPath(player:getPosition(), creature:getPosition(), 7, {ignoreLastCreature=true, ignoreNonPathable=true, ignoreCost=true}) local path = findPath(player:getPosition(), creature:getPosition(), 7, {ignoreLastCreature=true, ignoreNonPathable=true, ignoreCost=true, ignoreCreatures=true})
if creature:isMonster() and (oldTibia or creature:getType() < 3) and path then if creature:isMonster() and (oldTibia or creature:getType() < 3) and path then
local params = TargetBot.Creature.calculateParams(creature, path) -- return {craeture, config, danger, priority} local params = TargetBot.Creature.calculateParams(creature, path) -- return {craeture, config, danger, priority}
dangerLevel = dangerLevel + params.danger dangerLevel = dangerLevel + params.danger

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,599 @@
AttackEntry < UIWidget
background-color: alpha
text-offset: 18 1
focusable: true
height: 16
font: verdana-11px-rounded
text-align: left
CheckBox
id: enabled
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 15
height: 15
margin-top: 2
margin-left: 3
$focus:
background-color: #00000055
Button
id: remove
!text: tr('x')
anchors.right: parent.right
margin-right: 15
width: 15
height: 15
AttackBotBotPanel < Panel
height: 38
BotSwitch
id: title
anchors.top: parent.top
anchors.left: parent.left
text-align: center
width: 130
!text: tr('AttackBot')
Button
id: settings
anchors.top: prev.top
anchors.left: prev.right
anchors.right: parent.right
margin-left: 3
height: 17
text: Setup
Button
id: 1
anchors.top: prev.bottom
anchors.left: parent.left
text: 1
margin-right: 2
margin-top: 4
size: 17 17
Button
id: 2
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
text: 2
margin-left: 4
size: 17 17
Button
id: 3
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
text: 3
margin-left: 4
size: 17 17
Button
id: 4
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
text: 4
margin-left: 4
size: 17 17
Button
id: 5
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
text: 5
margin-left: 4
size: 17 17
Label
id: name
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
anchors.right: parent.right
text-align: center
margin-left: 4
height: 17
text: Profile #1
background: #292A2A
CategoryLabel < Panel
size: 315 15
image-source: /images/ui/panel_flat
image-border: 5
padding: 1
Label
id: description
anchors.fill: parent
text-align: center
text: Area Rune (avalanche, great fireball, etc)
font: verdana-11px-rounded
background: #363636
SourceLabel < Panel
size: 105 15
image-source: /images/ui/panel_flat
image-border: 5
padding: 1
Label
id: description
anchors.fill: parent
text-align: center
text: Monster Name
font: verdana-11px-rounded
background: #363636
RangeLabel < Panel
size: 323 15
image-source: /images/ui/panel_flat
image-border: 5
padding: 1
Label
id: description
anchors.fill: parent
text-align: center
text: 5 Sqm
font: verdana-11px-rounded
background: #363636
PreButton < PreviousButton
background: #363636
height: 15
NexButton < NextButton
background: #363636
height: 15
AttackBotPanel < Panel
size: 500 200
image-source: /images/ui/panel_flat
image-border: 5
padding: 5
TextList
id: entryList
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 3
size: 430 100
vertical-scrollbar: entryListScrollBar
VerticalScrollBar
id: entryListScrollBar
anchors.top: entryList.top
anchors.bottom: entryList.bottom
anchors.right: entryList.right
step: 14
pixels-scroll: true
PreButton
id: previousCategory
anchors.left: entryList.left
anchors.top: entryList.bottom
margin-top: 8
NexButton
id: nextCategory
anchors.left: category.right
anchors.top: entryList.bottom
margin-top: 8
margin-left: 2
CategoryLabel
id: category
anchors.top: entryList.bottom
anchors.left: previousCategory.right
anchors.verticalCenter: previousCategory.verticalCenter
margin-left: 3
PreButton
id: previousSource
anchors.left: entryList.left
anchors.top: category.bottom
margin-top: 8
NexButton
id: nextSource
anchors.left: source.right
anchors.top: category.bottom
margin-top: 8
margin-left: 2
SourceLabel
id: source
anchors.top: category.bottom
anchors.left: previousSource.right
anchors.verticalCenter: previousSource.verticalCenter
margin-left: 3
PreButton
id: previousRange
anchors.left: nextSource.right
anchors.verticalCenter: nextSource.verticalCenter
margin-left: 8
NexButton
id: nextRange
anchors.left: range.right
anchors.verticalCenter: range.verticalCenter
margin-left: 2
RangeLabel
id: range
anchors.left: previousRange.right
anchors.verticalCenter: previousRange.verticalCenter
margin-left: 3
TextEdit
id: monsters
anchors.left: entryList.left
anchors.top: range.bottom
margin-top: 5
size: 405 15
text: monster names
font: cipsoftFont
background: #363636
Label
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 6
margin-left: 3
text-align: center
text: Mana%:
font: verdana-11px-rounded
SpinBox
id: manaPercent
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 4
size: 30 20
minimum: 0
maximum: 99
step: 1
editable: true
focusable: true
Label
anchors.left: prev.right
margin-left: 7
anchors.verticalCenter: prev.verticalCenter
text: Creatures:
font: verdana-11px-rounded
SpinBox
id: creatures
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 4
size: 30 20
minimum: 1
maximum: 99
step: 1
editable: true
focusable: true
CheckBox
id: orMore
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 3
tooltip: or more creatures
Label
anchors.left: prev.right
margin-left: 7
anchors.verticalCenter: prev.verticalCenter
text: HP:
font: verdana-11px-rounded
SpinBox
id: minHp
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 4
size: 40 20
minimum: 0
maximum: 99
value: 0
editable: true
focusable: true
Label
anchors.left: prev.right
margin-left: 4
anchors.verticalCenter: prev.verticalCenter
text: -
font: verdana-11px-rounded
SpinBox
id: maxHp
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 4
size: 40 20
minimum: 1
maximum: 100
value: 100
editable: true
focusable: true
Label
anchors.left: prev.right
margin-left: 7
anchors.verticalCenter: prev.verticalCenter
text: CD:
font: verdana-11px-rounded
SpinBox
id: cooldown
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 4
size: 60 20
minimum: 0
maximum: 999999
step: 100
value: 0
editable: true
focusable: true
Button
id: up
anchors.right: parent.right
anchors.top: entryList.bottom
size: 60 17
text: Move Up
text-align: center
font: cipsoftFont
margin-top: 7
margin-right: 8
Button
id: down
anchors.right: prev.left
anchors.verticalCenter: prev.verticalCenter
size: 60 17
margin-right: 5
text: Move Down
text-align: center
font: cipsoftFont
Button
id: addEntry
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 40 19
text-align: center
text: New
font: cipsoftFont
BotItem
id: itemId
anchors.right: addEntry.left
margin-right: 5
anchors.bottom: parent.bottom
margin-bottom: 2
tooltip: drag item here on press to open window
TextEdit
id: spellName
anchors.top: monsters.top
anchors.left: monsters.right
anchors.right: parent.right
margin-left: 5
height: 15
text: spell name
background: #363636
font: cipsoftFont
visible: false
SettingsPanel < Panel
size: 500 200
image-source: /images/ui/panel_flat
image-border: 5
padding: 10
VerticalSeparator
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: Visible.right
margin-left: 10
margin-top: 5
margin-bottom: 5
Label
anchors.top: parent.top
anchors.left: prev.right
anchors.right: parent.right
margin-left: 10
text-align: center
font: verdana-11px-rounded
text: Profile:
TextEdit
id: profileName
anchors.top: prev.bottom
margin-top: 3
anchors.left: prev.left
anchors.right: prev.right
margin-left: 20
margin-right: 20
Button
id: resetSettings
anchors.right: parent.right
anchors.bottom: parent.bottom
text-align: center
text: Reset Settings
CheckBox
id: IgnoreMana
anchors.top: parent.top
anchors.left: parent.left
margin-top: 5
width: 200
text: Check RL Tibia conditions
CheckBox
id: Kills
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 200
height: 22
text: Don't use area attacks if less than kills to red skull
text-wrap: true
text-align: left
SpinBox
id: KillsAmount
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.left: prev.right
text-align: left
width: 30
minimum: 1
maximum: 10
focusable: true
margin-left: 5
CheckBox
id: Rotate
anchors.top: Kills.bottom
anchors.left: Kills.left
margin-top: 8
width: 220
text: Turn to side with most monsters
CheckBox
id: Cooldown
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 220
text: Check spell cooldowns
CheckBox
id: Visible
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: Items must be visible (recommended)
CheckBox
id: PvpMode
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: PVP mode
CheckBox
id: PvpSafe
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 245
text: PVP safe
CheckBox
id: BlackListSafe
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 200
height: 18
text: Stop if Anti-RS player in range
SpinBox
id: AntiRsRange
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.left: prev.right
text-align: center
width: 50
minimum: 1
maximum: 10
focusable: true
margin-left: 5
AttackBotWindow < MainWindow
size: 535 300
padding: 15
text: AttackBot v2
Label
id: mainLabel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 10
margin-left: 2
!text: tr('More important methods come first (Example: Exori gran above Exori)')
text-align: left
font: verdana-11px-rounded
color: #aeaeae
SettingsPanel
id: settingsPanel
anchors.top: prev.bottom
margin-top: 10
anchors.left: parent.left
margin-left: 2
Label
id: settingsLabel
anchors.verticalCenter: prev.top
anchors.left: prev.left
margin-left: 3
text: Settings
color: #fe4400
font: verdana-11px-rounded
AttackBotPanel
id: mainPanel
anchors.top: mainLabel.bottom
margin-top: 10
anchors.left: parent.left
margin-left: 2
visible: false
Label
id: shooterLabel
anchors.verticalCenter: prev.top
anchors.left: prev.left
margin-left: 3
text: Spell Shooter
color: #fe4400
font: verdana-11px-rounded
visible: false
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: closeButton.top
margin-bottom: 10
Button
id: closeButton
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
text: Close
font: cipsoftFont
Button
id: settings
anchors.left: parent.left
anchors.verticalCenter: prev.verticalCenter
size: 50 21
font: cipsoftFont
text: Settings

View File

@ -4,7 +4,6 @@ if type(storage[panelName]) ~= "table" then
storage[panelName] = { storage[panelName] = {
enabled = false; enabled = false;
purse = true; purse = true;
all = true;
list = { list = {
{ {
value = "Main Backpack", value = "Main Backpack",
@ -199,24 +198,13 @@ ContListsWindow < MainWindow
anchors.bottom: closeButton.top anchors.bottom: closeButton.top
margin-bottom: 8 margin-bottom: 8
CheckBox
id: all
anchors.left: parent.left
anchors.bottom: parent.bottom
text: Open All
tooltip: Opens all containers in main backpack.
width: 90
height: 15
margin-top: 2
margin-left: 3
CheckBox CheckBox
id: purse id: purse
anchors.left: prev.right anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
text: Open Purse text: Open Purse
tooltip: Opens Store/Charm Purse tooltip: Opens Store/Charm Purse
width: 90 width: 85
height: 15 height: 15
margin-top: 2 margin-top: 2
margin-left: 3 margin-left: 3
@ -227,7 +215,18 @@ ContListsWindow < MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
text: Sort Items text: Sort Items
tooltip: Sort items based on items widget tooltip: Sort items based on items widget
width: 90 width: 85
height: 15
margin-top: 2
margin-left: 15
CheckBox
id: forceOpen
anchors.left: prev.right
anchors.bottom: parent.bottom
text: Keep Open
tooltip: Will keep open containers all the time
width: 85
height: 15 height: 15
margin-top: 2 margin-top: 2
margin-left: 15 margin-left: 15
@ -292,7 +291,7 @@ function reopenBackpacks()
g_game.open(bpItem) g_game.open(bpItem)
end end
schedule(250, function() schedule(500, function()
local delay = 200 local delay = 200
if config.purse then if config.purse then
@ -301,33 +300,11 @@ function reopenBackpacks()
use(item) use(item)
end end
end end
if config.all then for i=1,#lstBPs do
local nextContainers = {} schedule(delay, function()
containers = getContainers() openContainer(lstBPs[i])
for i, container in pairs(g_game.getContainers()) do end)
for i, item in ipairs(container:getItems()) do delay = delay + 250
if item:isContainer() then
if item:isContainer() and config.all then
table.insert(nextContainers, item)
end
end
end
end
if #nextContainers > 0 then
for i = 1, #nextContainers do
schedule(delay, function()
g_game.open(nextContainers[i], nil)
end)
delay = delay + 250
end
end
else
for i=1,#lstBPs do
schedule(delay, function()
openContainer(lstBPs[i])
end)
delay = delay + 250
end
end end
end) end)
@ -371,12 +348,11 @@ if rootWidget then
end end
contListWindow.sort:setChecked(config.sort) contListWindow.sort:setChecked(config.sort)
contListWindow.all.onClick = function(widget) contListWindow.forceOpen.onClick = function(widget)
config.all = not config.all config.forceOpen = not config.forceOpen
contListWindow.all:setChecked(config.all) contListWindow.forceOpen:setChecked(config.forceOpen)
label.enabled:setTooltip(config.all and 'Opens all containers in main backpack.' or 'Opens listed containers from main backpack.')
end end
contListWindow.all:setChecked(config.all) contListWindow.forceOpen:setChecked(config.forceOpen)
local function refreshSortList(k, t) local function refreshSortList(k, t)
t = t or {} t = t or {}
@ -490,38 +466,58 @@ end
local function properTable(t) local function properTable(t)
local r = {} local r = {}
for _, entry in pairs(t) do for _, entry in pairs(t) do
table.insert(r, entry.id) if type(entry) == "number" then
table.insert(r, entry)
else
table.insert(r, entry.id)
end
end end
return r return r
end end
macro(100, function() macro(100, function()
if not config.sort then return end if not config.sort and not config.purse then return end
local storageVal = config.list local storageVal = config.list
for _, entry in pairs(storageVal) do for _, entry in pairs(storageVal) do
local dId = entry.item local dId = entry.item
local items = properTable(entry.items) local items = properTable(entry.items)
-- sorting
for _, container in pairs(getContainers()) do if config.sort then
local cName = container:getName():lower() for _, container in pairs(getContainers()) do
if not cName:find("depot") and not cName:find("depot") and not cName:find("quiver") then local cName = container:getName():lower()
local cId = container:getContainerItem():getId() if not cName:find("depot") and not cName:find("depot") and not cName:find("quiver") then
for __, item in ipairs(container:getItems()) do local cId = container:getContainerItem():getId()
local id = item:getId() for __, item in ipairs(container:getItems()) do
if table.find(items, id) and cId ~= dId then local id = item:getId()
local destination = getContainerByItem(dId) if table.find(items, id) and cId ~= dId then
if destination and not containerIsFull(destination) then local destination = getContainerByItem(dId, true)
return moveItem(item, destination) if destination and not containerIsFull(destination) then
return moveItem(item, destination)
end
end end
end end
end end
end end
end end
-- keep open / purse 23396
if config.forceOpen then
local container = getContainerByItem(dId)
if not container then
if getBack() and getBack():getId() == dId then
g_game.open(getBack())
else
local cItem = findItem(dId)
if cItem then
return g_game.open(cItem)
end
end
end
end
end
if config.purse and config.forceOpen and not getContainerByItem(23396) then
return use(getPurse())
end end
delay(900) delay(900)
end) end)

View File

@ -134,9 +134,9 @@ macro(200, function()
for __, item in ipairs(container:getItems()) do for __, item in ipairs(container:getItems()) do
for ___, userItem in ipairs(tables[i]) do for ___, userItem in ipairs(tables[i]) do
if item:getId() == userItem then if item:getId() == userItem then
return i == 1 and freecap() < 150 and g_game.move(item, pos(), item:getCount()) or return i == 1 and freecap() < 150 and dropItem(item) or
i == 2 and use(item) or i == 2 and use(item) or
g_game.move(item, pos(), item:getCount()) i == 3 and dropItem(item)
end end
end end
end end

View File

@ -622,7 +622,6 @@ macro(100, function()
end end
end end
standBySpells = true standBySpells = true
lastMana = mana()
end) end)
-- items -- items
@ -707,22 +706,15 @@ macro(100, function()
end end
end end
standByItems = true standByItems = true
lastMana = mana()
end) end)
UI.Separator() UI.Separator()
onAddThing(function(tile, thing) onPlayerHealthChange(function(healthPercent)
if thing == player then return end standByItems = false
if getDistanceBetween(tile:getPosition(), player:getPosition()) == 0 then standBySpells = false
standByItems = false
standBySpells = false
end
end) end)
macro(5000, function() onManaChange(function(player, mana, maxMana, oldMana, oldMaxMana)
if (standByItems or standBySpells) and mana() >= lastMana then standByItems = false
lastMana = mana() standBySpells = false
standByItems = false
standBySpells = false
end
end) end)

View File

@ -63,7 +63,7 @@ Panel
sioListWindow:hide() sioListWindow:hide()
-- TextWindow -- TextWindow
sioListWindow.spellName:setText(config.spellName) sioListWindow.spellName:setText(config.customSpellName)
sioListWindow.spellName.onTextChange = function(widget, text) sioListWindow.spellName.onTextChange = function(widget, text)
config.customSpellName = text config.customSpellName = text
end end

View File

@ -126,6 +126,7 @@ if rootWidget then
if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then
playSound("/sounds/Player_Detected.ogg") playSound("/sounds/Player_Detected.ogg")
delay(1500) delay(1500)
g_window.setTitle(name() .. " - Player Detected!")
if config.playerDetectedLogout then if config.playerDetectedLogout then
modules.game_interface.tryLogout(false) modules.game_interface.tryLogout(false)
end end
@ -142,6 +143,7 @@ if rootWidget then
if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then
playSound("/sounds/Creature_Detected.ogg") playSound("/sounds/Creature_Detected.ogg")
delay(1500) delay(1500)
g_window.setTitle(name() .. " - Creature Detected! ")
return return
end end
end end
@ -151,6 +153,7 @@ if rootWidget then
if config.healthBelow then if config.healthBelow then
if hppercent() <= config.healthValue then if hppercent() <= config.healthValue then
playSound("/sounds/Low_Health.ogg") playSound("/sounds/Low_Health.ogg")
g_window.setTitle(name() .. " - Low Health!")
delay(1500) delay(1500)
return return
end end
@ -159,6 +162,7 @@ if rootWidget then
if config.manaBelow then if config.manaBelow then
if manapercent() <= config.manaValue then if manapercent() <= config.manaValue then
playSound("/sounds/Low_Mana.ogg") playSound("/sounds/Low_Mana.ogg")
g_window.setTitle(name() .. " - Low Mana!")
delay(1500) delay(1500)
return return
end end
@ -168,6 +172,7 @@ if rootWidget then
onTalk(function(name, level, mode, text, channelId, pos) onTalk(function(name, level, mode, text, channelId, pos)
if mode == 4 and config.enabled and config.privateMessage then if mode == 4 and config.enabled and config.privateMessage then
playSound("/sounds/Private_Message.ogg") playSound("/sounds/Private_Message.ogg")
g_window.setTitle(name() .. " - Private Message")
return return
end end
end) end)

View File

@ -0,0 +1,437 @@
setDefaultTab("Main")
-- first, the variables
local launchTime = now
local startExp = exp()
local dmgTable = {}
local healTable = {}
local expTable = {}
local totalDmg = 0
local totalHeal = 0
local dmgDistribution = {}
local first = "-"
local second = "-"
local third = "-"
local bestHit = 0
local bestHeal = 0
local lootedItems = {}
local useData = {}
local usedItems ={}
local resetSessionData = function()
launchTime = now
startExp = exp()
dmgTable = {}
healTable = {}
expTable = {}
totalDmg = 0
totalHeal = 0
dmgDistribution = {}
first = "-"
second = "-"
third = "-"
bestHit = 0
bestHeal = 0
lootedItems = {}
useData = {}
usedItems ={}
refreshLoot()
refreshWaste()
end
function format_thousand(v)
if not v then return 0 end
local s = string.format("%d", math.floor(v))
local pos = string.len(s) % 3
if pos == 0 then pos = 3 end
return string.sub(s, 1, pos)
.. string.gsub(string.sub(s, pos+1), "(...)", ".%1")
end
local expGained = function()
return exp() - startExp
end
local expLeft = function()
local level = lvl()+1
return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200) - exp()
end
local niceTimeFormat = function(v) -- v in seconds
local hours = string.format("%02.f", math.floor(v/3600))
local mins = string.format("%02.f", math.floor(v/60 - (hours*60)))
return hours .. ":" .. mins .. "h"
end
local uptime
local sessionTime = function()
uptime = math.floor((now - launchTime)/1000)
return niceTimeFormat(uptime)
end
sessionTime()
local expPerHour = function(calculation)
local r = 0
if #expTable > 0 then
r = exp() - expTable[1]
else
return "-"
end
if uptime < 15*60 then
r = math.ceil((r/uptime)*60*60)
else
r = math.ceil(r*8)
end
if calculation then
return r
else
return format_thousand(r)
end
end
local timeToLevel = function()
local t = 0
if expPerHour(true) == 0 or expPerHour() == "-" then
return "-"
else
t = expLeft()/expPerHour(true)
return niceTimeFormat(math.ceil(t*60*60))
end
end
local sumT = function(t)
local s = 0
for i,v in pairs(t) do
s = s + v.d
end
return s
end
local valueInSeconds = function(t)
local d = 0
local time = 0
if #t > 0 then
for i, v in ipairs(t) do
if now - v.t <= 3000 then
if time == 0 then
time = v.t
end
d = d + v.d
else
table.remove(t, 1)
end
end
end
return math.ceil(d/((now-time)/1000))
end
local regex = "You lose ([0-9]*) hitpoints due to an attack by ([a-z]*) ([a-z A-z-]*)"
onTextMessage(function(mode, text)
if mode == 21 then -- damage dealt
totalDmg = totalDmg + getFirstNumberInText(text)
table.insert(dmgTable, {d = getFirstNumberInText(text), t = now})
if getFirstNumberInText(text) > bestHit then
bestHit = getFirstNumberInText(text)
end
end
if mode == 23 then -- healing
totalHeal = totalHeal + getFirstNumberInText(text)
table.insert(healTable, {d = getFirstNumberInText(text), t = now})
if getFirstNumberInText(text) > bestHeal then
bestHeal = getFirstNumberInText(text)
end
end
-- damage distribution part
if text:find("You lose") then
local data = regexMatch(text, regex)[1]
if data then
local monster = data[4]
local val = data[2]
table.insert(dmgDistribution, {v=val,m=monster,t=now})
end
end
end)
-- tables maintance
macro(500, function()
local dmgFinal = {}
local labelTable = {}
local dmgSum = 0
table.insert(expTable, exp())
if #expTable > 15*60 then
for i,v in pairs(expTable) do
if i == 1 then
table.remove(expTable, i)
end
end
end
for i,v in pairs(dmgDistribution) do
if now - v.t > 60*1000*10 then
table.remove(dmgDistribution, i)
else
dmgSum = dmgSum + v.v
if not dmgFinal[v.m] then
dmgFinal[v.m] = v.v
else
dmgFinal[v.m] = dmgFinal[v.m] + v.v
end
end
end
if not dmgFinal[1] then
first = "-"
end
if not dmgFinal[2] then
second = "-"
end
if not dmgFinal[3] then
third = "-"
end
local iter = 0
for k,v in pairs(dmgFinal) do
table.insert(labelTable, {m=k, d=tonumber(v)})
end
table.sort(labelTable, function(a,b) return a.d > b.d end)
for i,v in pairs(labelTable) do
local label = v.m .. ": " .. math.floor((v.d/dmgSum)*100) .. "%"
if i == 1 then
first = label
elseif i == 2 then
second = label
elseif i == 3 then
third = label
end
end
end)
-- visuals
UI.Separator()
local main = UI.createWidget("MainAnalyzer")
local ui = UI.createWidget("HuntingAnalyzer")
local ui2 = UI.createWidget("LootAnalyzer")
ui:hide()
ui2:hide()
function refreshLoot()
for i, child in pairs(ui2.List:getChildren()) do
child:destroy()
end
for k,v in pairs(lootedItems) do
local label = g_ui.createWidget("LootItemLabel", ui2.List)
label:setText(v .. "x " .. k)
end
end
function refreshWaste()
for i, child in pairs(ui2.supplyList:getChildren()) do
child:destroy()
end
for k,v in pairs(usedItems) do
local label = g_ui.createWidget("LootItemLabel", ui2.supplyList)
label:setText(v .. "x " .. k)
end
end
-- loot analyzer
-- adding
local containers = CaveBot.GetLootContainers()
local lastCap = freecap()
onAddItem(function(container, slot, item, oldItem)
if not table.find(containers, container:getContainerItem():getId()) then return end
if isInPz() then return end
if slot > 0 then return end
if freecap() >= lastCap then return end
local name = item:getId() == 3031 and "gold coin" or item:getId() == 3035 and "platinum coin" or item:getId() == 3043 and "crystal coin" or item:getMarketData().name
if not lootedItems[name] then
lootedItems[name] = item:getCount()
else
lootedItems[name] = lootedItems[name] + item:getCount()
end
refreshLoot()
end)
onContainerUpdateItem(function(container, slot, item, oldItem)
if not table.find(containers, container:getContainerItem():getId()) then return end
if not oldItem then return end
if isInPz() then return end
if freecap() == lastCap then return end
local name = item:getId() == 3031 and "gold coin" or item:getId() == 3035 and "platinum coin" or item:getId() == 3043 and "crystal coin" or item:getMarketData().name
local amount = item:getCount() - oldItem:getCount()
if not lootedItems[name] then
lootedItems[name] = amount
else
lootedItems[name] = lootedItems[name] + amount
end
refreshLoot()
end)
-- waste
local regex3 = [[\d ([a-z A-Z]*)s...]]
useData = {}
usedItems = {}
onTextMessage(function(mode, text)
text = text:lower()
if not text:find("using one of") then return end
local amount = getFirstNumberInText(text)
local re = regexMatch(text, regex3)
local name = re[1][2]
if not useData[name] then
useData[name] = amount
else
if math.abs(useData[name]-amount) == 1 then
useData[name] = amount
if not usedItems[name] then
usedItems[name] = 1
else
usedItems[name] = usedItems[name] + 1
end
end
end
refreshWaste()
end)
function toggleBetween()
if ui:isVisible() then
ui:hide()
ui2:show()
main.change:setText("Hunt")
else
ui:show()
ui2:hide()
main.change:setText("Loot")
end
end
function hideAll()
if not ui:isVisible() and not ui2:isVisible() then
ui:show()
ui2:hide()
else
ui:hide()
ui2:hide()
end
end
main.reset.onClick = function(widget)
resetSessionData()
end
main.toggle.onClick = function(widget)
hideAll()
end
main.change.onClick = function(widget)
toggleBetween()
end
function hourVal(v)
return (v/uptime)*3600
end
local lootWorth
local wasteWorth
local balance
local balanceDesc
local hourDesc
local desc
local hour
function bottingStats()
lootWorth = 0
wasteWorth = 0
for k, v in pairs(lootedItems) do
if LootItems[k] then
lootWorth = lootWorth + (LootItems[k]*v)
end
end
for k, v in pairs(usedItems) do
if LootItems[k] then
wasteWorth = wasteWorth + (LootItems[k]*v)
end
end
balance = lootWorth - wasteWorth
return lootWorth, wasteWorth, balance
end
function bottingLabels(lootWorth, wasteWorth, balance)
balanceDesc = nil
hourDesc = nil
desc = nil
if balance >= 1000000 or balance <= -1000000 then
desc = balance / 1000000
balanceDesc = math.floor(desc) .. "." .. math.floor(desc * 10) % 10 .. "kk"
elseif balance >= 1000 or balance <= -1000 then
desc = balance / 1000
balanceDesc = math.floor(desc) .. "." .. math.floor(desc * 10) % 10 .."k"
else
balanceDesc = balance .. "gp"
end
hour = hourVal(balance)
if hour >= 1000000 or hour <= -1000000 then
desc = balance / 1000000
hourDesc = math.floor(hourVal(desc)) .. "." .. math.floor(hourVal(desc) * 10) % 10 .. "kk/h"
elseif hour >= 1000 or hour <= -1000 then
desc = balance / 1000
hourDesc = math.floor(hourVal(desc)) .. "." .. math.floor(hourVal(desc) * 10) % 10 .. "k/h"
else
hourDesc = math.floor(hourVal(balance)) .. "gp/h"
end
return balanceDesc, hourDesc
end
function reportStats()
local lootWorth, wasteWorth, balance = bottingStats()
local balanceDesc, hourDesc = bottingLabels(lootWorth, wasteWorth, balance)
local a, b, c
a = "Session Time: " .. sessionTime() .. ", Exp Gained: " .. format_thousand(expGained()) .. ", Exp/h: " .. expPerHour()
b = " | Balance: " .. balanceDesc .. " (" .. hourDesc .. ")"
c = a..b
return c
end
macro(500, function()
local lootWorth, wasteWorth, balance = bottingStats()
local balanceDesc, hourDesc = bottingLabels(lootWorth, wasteWorth, balance)
-- hunting
ui.one:setText(sessionTime())
ui.two:setText(format_thousand(expGained()))
ui.three:setText(expPerHour())
ui.four:setText(timeToLevel())
ui.five:setText(format_thousand(burstDamageValue()))
ui.six:setText(format_thousand(totalDmg))
ui.seven:setText(format_thousand(valueInSeconds(dmgTable)))
ui.eight:setText(format_thousand(bestHit))
ui.nine:setText(format_thousand(totalHeal))
ui.ten:setText(format_thousand(valueInSeconds(healTable)))
ui.eleven:setText(format_thousand(bestHeal))
ui.dOne:setText(first)
ui.dTwo:setText(second)
ui.dThree:setText(third)
-- loot
ui2.loot:setText(format_thousand(lootWorth))
ui2.lootHour:setText(format_thousand(hourVal(lootWorth)))
ui2.supplies:setText(format_thousand(wasteWorth))
ui2.suppliesHour:setText(format_thousand(hourVal(wasteWorth)))
ui.balance:setColor(balance >= 0 and "green" or "red")
ui.balance:setText(balanceDesc .. " (" .. hourDesc .. ")")
end)

View File

@ -0,0 +1,367 @@
LootItemLabel < Label
opacity: 0.87
text-offset: 2 0
focusable: false
height: 16
MainAnalyzer < Panel
height: 45
padding: 4
BotButton
id: toggle
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text: Session Analyzer
BotButton
id: reset
anchors.top: prev.bottom
margin-top: 4
anchors.left: parent.left
anchors.right: parent.horizontalCenter
margin-right: 2
text: Reset
BotButton
id: change
anchors.top: toggle.bottom
margin-top: 4
anchors.left: parent.horizontalCenter
margin-left: 2
anchors.right: toggle.right
text-align: center
text: Loot
HuntingAnalyzer < Panel
height: 275
padding: 5
Label
id: SessionLabel
anchors.top: parent.top
anchors.left: parent.left
text: Session:
Label
id: XpGainLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: XP Gain:
Label
id: XpHourLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: XP/h:
Label
id: NextLevelLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Next Level:
Label
id: BalanceLabel
anchors.top: prev.bottom
margin-top: 5
anchors.left: parent.left
text: Balance
Label
id: BurstDamageLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Burst Damage:
Label
id: DamageDealtLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Damage Dealt:
Label
id: DPSLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: DPS:
Label
id: BestHitLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Best Hit:
Label
id: HealingDoneLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Healing Done:
Label
id: HPSLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: HPS:
Label
id: BestHealLabel
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text: Best Heal:
Label
id: one
anchors.right: parent.right
anchors.verticalCenter: SessionLabel.verticalCenter
text-align: right
text: 00:00h
width: 150
Label
id: two
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: three
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: -
width: 150
Label
id: four
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: -
width: 150
Label
id: balance
anchors.top: prev.bottom
anchors.right: parent.right
margin-top: 5
text: 0
text-align: right
width: 150
Label
id: five
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: six
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: -
width: 150
Label
id: seven
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: eight
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: nine
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: ten
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
Label
id: eleven
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
text-align: right
text: 0
width: 150
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
Label
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
text-align: center
text: Damage Distribution
Label
id: dOne
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
text-align: center
text: -
Label
id: dTwo
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
text-align: center
text: -
Label
id: dThree
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
text-align: center
text: -
LootAnalyzer < Panel
height: 275
padding: 4
Label
id: first
anchors.top: parent.top
anchors.left: parent.left
text: Supplies
Label
anchors.top: prev.bottom
margin-top: 5
anchors.left: parent.left
text: Supplies/h
TextList
id: supplyList
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
height: 50
vertical-scrollbar: supplyListScrollBar
Label
id: second
anchors.top: prev.bottom
margin-top: 5
anchors.left: parent.left
text: Loot
Label
anchors.top: prev.bottom
margin-top: 5
anchors.left: parent.left
text: Loot/h
Label
id: supplies
anchors.top: parent.top
anchors.right: parent.right
width: 150
text: 0
text-align: right
Label
id: suppliesHour
anchors.top: prev.bottom
anchors.right: parent.right
margin-top: 5
text: 0
text-align: right
width: 150
Label
id: loot
anchors.top: second.top
anchors.right: parent.right
width: 150
text: 0
text-align: right
Label
id: lootHour
anchors.top: prev.bottom
anchors.right: parent.right
margin-top: 5
text: 0
text-align: right
width: 150
TextList
id: List
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
height: 120
vertical-scrollbar: ListScrollBar
VerticalScrollBar
id: ListScrollBar
anchors.top: List.top
anchors.bottom: List.bottom
anchors.right: List.right
step: 14
pixels-scroll: true
VerticalScrollBar
id: supplyListScrollBar
anchors.top: supplyList.top
anchors.bottom: supplyList.bottom
anchors.right: supplyList.right
step: 14
pixels-scroll: true

View File

@ -2,7 +2,7 @@
-- visit http://bot.otclient.ovh/ -- visit http://bot.otclient.ovh/
local cavebotTab = "Cave" local cavebotTab = "Cave"
local targetingTab = "Target" local targetingTab = storage.extras.joinBot and "Cave" or "Target"
setDefaultTab(cavebotTab) setDefaultTab(cavebotTab)
CaveBot.Extensions = {} CaveBot.Extensions = {}
@ -15,6 +15,7 @@ dofile("/cavebot/editor.lua")
dofile("/cavebot/example_functions.lua") dofile("/cavebot/example_functions.lua")
dofile("/cavebot/recorder.lua") dofile("/cavebot/recorder.lua")
dofile("/cavebot/walking.lua") dofile("/cavebot/walking.lua")
dofile("/cavebot/minimap.lua")
-- in this section you can add extensions, check extension_template.lua -- in this section you can add extensions, check extension_template.lua
--dofile("/cavebot/extension_template.lua") --dofile("/cavebot/extension_template.lua")
dofile("/cavebot/sell_all.lua") dofile("/cavebot/sell_all.lua")
@ -35,6 +36,7 @@ dofile("/cavebot/tasker.lua")
dofile("/cavebot/cavebot.lua") dofile("/cavebot/cavebot.lua")
setDefaultTab(targetingTab) setDefaultTab(targetingTab)
if storage.extras.joinBot then UI.Label("-- [[ TargetBot ]] --") end
TargetBot = {} -- global namespace TargetBot = {} -- global namespace
importStyle("/targetbot/looting.otui") importStyle("/targetbot/looting.otui")
importStyle("/targetbot/target.otui") importStyle("/targetbot/target.otui")

View File

@ -94,7 +94,10 @@ addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel)
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel) addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel)
addScrollBar("huntRoutes", "Hunting Routes Limit", 0, 300, 50, leftPanel) addScrollBar("huntRoutes", "Hunting Routes Limit", 0, 300, 50, leftPanel)
addScrollBar("killUnder", "Kill monsters below", 0, 100, 30, leftPanel) addScrollBar("killUnder", "Kill monsters below", 0, 100, 30, leftPanel)
addScrollBar("gotoMaxDistance", "Max GoTo Distance", 0, 127, 30, leftPanel)
addCheckBox("lootLast", "Start loot from last corpse", true, leftPanel) addCheckBox("lootLast", "Start loot from last corpse", true, leftPanel)
addCheckBox("joinBot", "Join TargetBot and CaveBot", false, leftPanel)
addCheckBox("reachable", "Target only pathable mobs", false, leftPanel)
addCheckBox("title", "Custom Window Title", true, rightPanel) addCheckBox("title", "Custom Window Title", true, rightPanel)
if true then if true then
@ -123,19 +126,33 @@ if true then
end) end)
end end
addCheckBox("separatePm", "Open PM's in new Window", false, rightPanel)
if true then
onTalk(function(name, level, mode, text, channelId, pos)
if mode == 4 and settings.separatePm then
local g_console = modules.game_console
local privateTab = g_console.getTab(name)
if privateTab == nil then
privateTab = g_console.addTab(name, true)
g_console.addPrivateText(g_console.applyMessagePrefixies(name, level, text), g_console.SpeakTypesSettings['private'], name, false, name)
end
return
end
end)
end
addTextEdit("useAll", "Use All Hotkey", "space", rightPanel) addTextEdit("useAll", "Use All Hotkey", "space", rightPanel)
if true then if true then
local useId = {34847, 1764, 21051, 30823, 6264, 5282, 20453, 20454, 20474, 11708, 11705, local useId = { 34847, 1764, 21051, 30823, 6264, 5282, 20453, 20454, 20474, 11708, 11705,
6257, 6256, 2772, 27260, 2773, 1632, 1633, 1948, 435, 6252, 6253, 5007, 4911, 6257, 6256, 2772, 27260, 2773, 1632, 1633, 1948, 435, 6252, 6253, 5007, 4911,
1629, 1630, 5108, 5107, 5281, 1968, 435, 1948, 5542, 31116, 31120, 30742, 31115, 1629, 1630, 5108, 5107, 5281, 1968, 435, 1948, 5542, 31116, 31120, 30742, 31115,
31118, 20474, 5737, 5736, 5734, 5733, 31202, 31228, 31199, 31200, 33262, 30824, 31118, 20474, 5737, 5736, 5734, 5733, 31202, 31228, 31199, 31200, 33262, 30824,
5125, 5126, 5116, 5117, 8257, 8258, 8255, 8256, 5120, 30777, 30776, 23873, 23877, 5125, 5126, 5116, 5117, 8257, 8258, 8255, 8256, 5120, 30777, 30776, 23873, 23877,
5736, 6264, 31262, 31130, 31129, 6250, 6249, 5122, 30049} 5736, 6264, 31262, 31130, 31129, 6250, 6249, 5122, 30049, 7131, 7132, 7727 }
local shovelId = {606, 593, 867} local shovelId = { 606, 593, 867 }
local ropeId = {17238, 12202, 12935, 386, 421, 21966, 14238} local ropeId = { 17238, 12202, 12935, 386, 421, 21966, 14238 }
local macheteId = {2130, 3696} local macheteId = { 2130, 3696 }
local scytheId = {3653} local scytheId = { 3653 }
setDefaultTab("Tools") setDefaultTab("Tools")
-- script -- script
@ -286,7 +303,7 @@ if true then
7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642, 7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642,
6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116, 6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116,
1632, 11705, 30772, 30774, 6248, 5735, 5732, 5120, 23873, 5736, 1632, 11705, 30772, 30774, 6248, 5735, 5732, 5120, 23873, 5736,
6264, 5122, 30049, 30042 } 6264, 5122, 30049, 30042, 7727 }
function checkForDoors(pos) function checkForDoors(pos)
local tile = g_map.getTile(pos) local tile = g_map.getTile(pos)
@ -373,14 +390,19 @@ if true then
end) end)
end end
addCheckBox("holdMwall", "Hold MW/WG [ , ][ . ]", true, rightPanel) addCheckBox("holdMwall", "Hold MW/WG", true, rightPanel)
addTextEdit("holdMwHot", "Magic Wall Hotkey: ", "F5", rightPanel)
addTextEdit("holdWgHot", "Wild Growth Hotkey: ", "F6", rightPanel)
if true then if true then
local mwHot = "," local mwHot
local wgHot = "." local wgHot
local candidates = {} local candidates = {}
local m = macro(20, function() local m = macro(20, function()
mwHot = settings.holdMwHot
wgHot = settings.holdWgHot
if not settings.holdMwall then return end if not settings.holdMwall then return end
if #candidates == 0 then return end if #candidates == 0 then return end
@ -388,7 +410,7 @@ if true then
if tile:getText():len() == 0 then if tile:getText():len() == 0 then
table.remove(candidates, i) table.remove(candidates, i)
end end
local rune = tile:getText() == "HOLD MW" and 3180 or 3156 local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
if tile:canShoot() and not isInPz() and tile:isWalkable() and tile:getTopUseThing():getId() ~= 2130 then if tile:canShoot() and not isInPz() and tile:isWalkable() and tile:getTopUseThing():getId() ~= 2130 then
return useWith(rune, tile:getTopUseThing()) return useWith(rune, tile:getTopUseThing())
end end
@ -398,9 +420,10 @@ if true then
onRemoveThing(function(tile, thing) onRemoveThing(function(tile, thing)
if not settings.holdMwall then return end if not settings.holdMwall then return end
if thing:getId() ~= 2129 then return end if thing:getId() ~= 2129 then return end
if tile:getText():len() > 0 then if tile:getText():find("HOLD") then
table.insert(candidates, tile) table.insert(candidates, tile)
useWith(3180, tile:getTopUseThing()) local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
useWith(rune, tile:getTopUseThing())
end end
end) end)
@ -439,22 +462,18 @@ end
addCheckBox("checkPlayer", "Check Players", true, rightPanel) addCheckBox("checkPlayer", "Check Players", true, rightPanel)
if true then if true then
local found
local function checkPlayers() local function checkPlayers()
local found = false
for i, spec in ipairs(getSpectators()) do for i, spec in ipairs(getSpectators()) do
if spec:isPlayer() and spec:getText() == "" and spec:getPosition().z == posz() and spec ~= player then if spec:isPlayer() and spec:getText() == "" and spec:getPosition().z == posz() and spec ~= player then
g_game.look(spec) g_game.look(spec)
found = true found = now
end end
end end
if found then
schedule(20, function() modules.game_textmessage.clearMessages() end)
schedule(40, function() modules.game_textmessage.clearMessages() end)
schedule(60, function() modules.game_textmessage.clearMessages() end)
end
end end
checkPlayers() if settings.checkPlayer then
checkPlayers()
end
onPlayerPositionChange(function(x,y) onPlayerPositionChange(function(x,y)
if not settings.checkPlayer then return end if not settings.checkPlayer then return end
@ -465,22 +484,15 @@ if true then
onCreatureAppear(function(creature) onCreatureAppear(function(creature)
if not settings.checkPlayer then return end if not settings.checkPlayer then return end
local found = false
if creature:isPlayer() and creature:getText() == "" and creature:getPosition().z == posz() and creature ~= player then if creature:isPlayer() and creature:getText() == "" and creature:getPosition().z == posz() and creature ~= player then
g_game.look(creature) g_game.look(creature)
found = true found = now
end
if found then
schedule(20, function() modules.game_textmessage.clearMessages() end)
schedule(40, function() modules.game_textmessage.clearMessages() end)
schedule(60, function() modules.game_textmessage.clearMessages() end)
end end
end) end)
local regex = [[You see ([a-z 'A-z-]*) \(Level ([0-9]*)\)]] local regex = [[You see ([a-z 'A-z-]*) \(Level ([0-9]*)\)]]
onTextMessage(function(mode, text) onTextMessage(function(mode, text)
if not settings.checkPlayer then return end if not settings.checkPlayer then return end
if mode ~= 20 then return end
local re = regexMatch(text, regex) local re = regexMatch(text, regex)
if #re ~= 0 then if #re ~= 0 then
@ -500,6 +512,9 @@ if true then
if creature then if creature then
creature:setText(level..voc) creature:setText(level..voc)
end end
if found and now - found < 500 then
modules.game_textmessage.clearMessages()
end
end end
end) end)
end end

View File

@ -39,6 +39,7 @@ ExtrasTextEdit < Panel
minimum: 0 minimum: 0
maximum: 10 maximum: 10
step: 1 step: 1
text-align: center
ExtrasItem < Panel ExtrasItem < Panel
height: 34 height: 34

View File

@ -1230,5 +1230,38 @@ LootItems = {
["ultimate health potion"] = 379, ["ultimate health potion"] = 379,
["supreme health potion"] = 625, ["supreme health potion"] = 625,
["great spirit potion"] = 228, ["great spirit potion"] = 228,
["ultimate spirit potion"] = 438 ["ultimate spirit potion"] = 438,
-- runes
["cure poison rune"] = 65,
["poison field rune"] = 21,
["fire field rune"] = 28,
["intense healing rune"] = 95,
["destroy field rune"] = 15,
["energy field rune"] = 38,
["stalagmite rune"] = 12,
["heavy magic missile rune"] = 12,
["disintegrate rune"] = 26,
["ultimate healing rune"] = 175,
["poison bomb rune"] = 85,
["animate death rune"] = 375,
["chameleon rune"] = 210,
["fireball rune"] = 30,
["holy missile rune"] = 16,
["icicle rune"] = 30,
["stone shower rune"] = 37,
["thunderstorm rune"] = 47,
["avalanche rune"] = 57,
["great fireball rune"] = 57,
["convince creature rune"] = 80,
["fire bomb rune"] = 147,
["poison wall rune"] = 52,
["explosion rune"] = 31,
["fire wall rune"] = 61,
["soulfire rune"] = 46,
["wild growth rune"] = 160,
["magic wall rune"] = 116,
["energy wall rune"] = 85,
["energy bomb rune"] = 203,
["sudden death rune"] = 135,
["paralyse rune"] = 700
} }

View File

@ -1,3 +1,3 @@
UI.Label("vBot 3.01 \n Vithrax#5814") UI.Label("vBot v3.4 \n Vithrax#5814")
UI.Button("Official OTCv8 Discord!", function() g_platform.openUrl("https://discord.gg/yhqBE4A") end) UI.Button("Official OTCv8 Discord!", function() g_platform.openUrl("https://discord.gg/yhqBE4A") end)
UI.Separator() UI.Separator()

View File

@ -24,6 +24,9 @@ local LOCKER_ACCESSTILE_MODIFIERS = {
local function CaveBotConfigParse() local function CaveBotConfigParse()
local name = storage["_configs"]["targetbot_configs"]["selected"] local name = storage["_configs"]["targetbot_configs"]["selected"]
if not name then
return warn("[vBot] Please create a new TargetBot config and reset bot")
end
local file = configDir .. "/targetbot_configs/" .. name .. ".json" local file = configDir .. "/targetbot_configs/" .. name .. ".json"
local data = g_resources.readFileContents(file) local data = g_resources.readFileContents(file)
return Config.parse(data)['looting'] return Config.parse(data)['looting']
@ -72,11 +75,13 @@ CaveBot.Status = "waiting"
--- Parses config and extracts loot list. --- Parses config and extracts loot list.
-- @return table -- @return table
function CaveBot.GetLootItems() function CaveBot.GetLootItems()
local t = CaveBotConfigParse()["items"] local t = CaveBotConfigParse() and CaveBotConfigParse()["items"] or nil
local returnTable = {} local returnTable = {}
for i, item in pairs(t) do if type(t) == "table" then
table.insert(returnTable, item["id"]) for i, item in pairs(t) do
table.insert(returnTable, item["id"])
end
end end
return returnTable return returnTable
@ -102,11 +107,13 @@ end
--- Parses config and extracts loot containers. --- Parses config and extracts loot containers.
-- @return table -- @return table
function CaveBot.GetLootContainers() function CaveBot.GetLootContainers()
local t = CaveBotConfigParse()["containers"] local t = CaveBotConfigParse() and CaveBotConfigParse()["containers"] or nil
local returnTable = {} local returnTable = {}
for i, container in pairs(t) do if type(t) == "table" then
table.insert(returnTable, container["id"]) for i, container in pairs(t) do
table.insert(returnTable, container["id"])
end
end end
return returnTable return returnTable
@ -429,7 +436,7 @@ function CaveBot.WithdrawItem(id, amount, fromDepot, destination)
destination = getContainerByName(destination) destination = getContainerByName(destination)
end end
local itemCount = itemAmount(id) local itemCount = itemAmount(id)
test()
local depot local depot
for i, container in pairs(getContainers()) do for i, container in pairs(getContainers()) do
if container:getName():lower():find("depot box") or container:getName():lower():find("your inbox") then if container:getName():lower():find("depot box") or container:getName():lower():find("your inbox") then

View File

@ -93,33 +93,37 @@ Panel
if config.highlight then if config.highlight then
creature:setMarked('#0000FF') creature:setMarked('#0000FF')
end end
specOutfit.head = 88 if config.outfits then
specOutfit.body = 88 specOutfit.head = 88
specOutfit.legs = 88 specOutfit.body = 88
specOutfit.feet = 88 specOutfit.legs = 88
if storage.BOTserver.outfit then specOutfit.feet = 88
local voc = vBot.BotServerMembers[creature:getName()] if storage.BOTserver.outfit then
specOutfit.addons = 3 local voc = vBot.BotServerMembers[creature:getName()]
if voc == 1 then specOutfit.addons = 3
specOutfit.type = 131 if voc == 1 then
elseif voc == 2 then specOutfit.type = 131
specOutfit.type = 129 elseif voc == 2 then
elseif voc == 3 then specOutfit.type = 129
specOutfit.type = 130 elseif voc == 3 then
elseif voc == 4 then specOutfit.type = 130
specOutfit.type = 144 elseif voc == 4 then
specOutfit.type = 144
end
end end
creature:setOutfit(specOutfit)
end end
creature:setOutfit(specOutfit)
elseif isEnemy(specName) then elseif isEnemy(specName) then
if config.highlight then if config.highlight then
creature:setMarked('#FF0000') creature:setMarked('#FF0000')
end end
specOutfit.head = 94 if config.outfits then
specOutfit.body = 94 specOutfit.head = 94
specOutfit.legs = 94 specOutfit.body = 94
specOutfit.feet = 94 specOutfit.legs = 94
creature:setOutfit(specOutfit) specOutfit.feet = 94
creature:setOutfit(specOutfit)
end
end end
end end

View File

@ -1,15 +1,18 @@
-- tools tab -- tools tab
setDefaultTab("Tools") setDefaultTab("Tools")
local moneyIds = {3031, 3035} -- gold coin, platinium coin if type(storage.moneyItems) ~= "table" then
storage.moneyItems = {3031, 3035}
end
macro(1000, "Exchange money", function() macro(1000, "Exchange money", function()
if not storage.moneyItems[1] then return end
local containers = g_game.getContainers() local containers = g_game.getContainers()
for index, container in pairs(containers) do for index, container in pairs(containers) do
if not container.lootContainer then -- ignore monster containers if not container.lootContainer then -- ignore monster containers
for i, item in ipairs(container:getItems()) do for i, item in ipairs(container:getItems()) do
if item:getCount() == 100 then if item:getCount() == 100 then
for m, moneyId in ipairs(moneyIds) do for m, moneyId in ipairs(storage.moneyItems) do
if item:getId() == moneyId then if item:getId() == moneyId.id then
return g_game.use(item) return g_game.use(item)
end end
end end
@ -19,6 +22,12 @@ macro(1000, "Exchange money", function()
end end
end) end)
local moneyContainer = UI.Container(function(widget, items)
storage.moneyItems = items
end, true)
moneyContainer:setHeight(35)
moneyContainer:setItems(storage.moneyItems)
UI.Separator() UI.Separator()
macro(60000, "Send message on trade", function() macro(60000, "Send message on trade", function()

View File

@ -14,8 +14,6 @@ vBot.isUsingPotion = false
vBot.isUsing = false vBot.isUsing = false
-- scripts / functions -- scripts / functions
onPlayerPositionChange(function(x,y) onPlayerPositionChange(function(x,y)
vBot.standTime = now vBot.standTime = now
@ -64,6 +62,10 @@ function whiteInfoMessage(text)
return modules.game_textmessage.displayGameMessage(text) return modules.game_textmessage.displayGameMessage(text)
end end
function statusMessage(text, logInConsole)
return not logInConsole and modules.game_textmessage.displayFailureMessage(text) or modules.game_textmessage.displayStatusMessage(text)
end
-- same as above but red message -- same as above but red message
function broadcastMessage(text) function broadcastMessage(text)
return modules.game_textmessage.displayBroadcastMessage(text) return modules.game_textmessage.displayBroadcastMessage(text)
@ -150,19 +152,34 @@ function containerIsFull(c)
end end
function dropItem(idOrObject)
if type(idOrObject) == "number" then
idOrObject = findItem(idOrObject)
end
g_game.move(idOrObject, pos(), idOrObject:getCount())
end
-- not perfect function to return whether character has utito tempo buff -- not perfect function to return whether character has utito tempo buff
-- known to be bugged if received debuff (ie. roshamuul) -- known to be bugged if received debuff (ie. roshamuul)
-- TODO: simply a better version -- TODO: simply a better version
-- returns boolean -- returns boolean
function isBuffed() function isBuffed()
local var = false local var = false
if not hasPartyBuff() then return var end
local skillId = 0
for i = 1, 4 do for i = 1, 4 do
local premium = (player:getSkillLevel(i) - player:getSkillBaseLevel(i)) if player:getSkillBaseLevel(i) > player:getSkillBaseLevel(skillId) then
local base = player:getSkillBaseLevel(i) skillId = i
if hasPartyBuff() and (premium / 100) * 305 > base then
var = true
end end
end end
local premium = (player:getSkillLevel(skillId) - player:getSkillBaseLevel(skillId))
local base = player:getSkillBaseLevel(skillId)
if (premium / 100) * 305 > base then
var = true
end
return var return var
end end
@ -361,7 +378,7 @@ function isFriend(c)
if p:isLocalPlayer() then return true end if p:isLocalPlayer() then return true end
if p:isPlayer() then if p:isPlayer() then
if ((p:getShield() >= 3 and p:getShield() <= 10) or p:getEmblem() == if ((p:getShield() >= 3 and p:getShield() <= 10) or p:getEmblem() ==
2) then 1) then
CachedFriends[c] = true CachedFriends[c] = true
CachedFriends[p] = true CachedFriends[p] = true
return true return true
@ -391,7 +408,7 @@ function isEnemy(c)
if p:isLocalPlayer() then return end if p:isLocalPlayer() then return end
if p:isPlayer() and table.find(storage.playerList.enemyList, name) or if p:isPlayer() and table.find(storage.playerList.enemyList, name) or
(storage.playerList.marks and not isFriend(name)) then (storage.playerList.marks and not isFriend(name)) or p:getEmblem() == 2 then
return true return true
else else
return false return false
@ -673,35 +690,10 @@ function itemAmount(id)
end end
end end
end end
if getHead() and getHead():getId() == id then
totalItemCount = totalItemCount + getHead():getCount() local slots = {getHead(), getNeck(), getBack(), getBody(), getRight(), getLeft(), getLeg(), getFeet(), getFinger(), getAmmo()}
end for i, slot in pairs(slots) do
if getNeck() and getNeck():getId() == id then totalItemCount = slot and slot:getId() == id and totalItemCount + 1 or totalItemCount
totalItemCount = totalItemCount + getNeck():getCount()
end
if getBack() and getBack():getId() == id then
totalItemCount = totalItemCount + getBack():getCount()
end
if getBody() and getBody():getId() == id then
totalItemCount = totalItemCount + getBody():getCount()
end
if getRight() and getRight():getId() == id then
totalItemCount = totalItemCount + getRight():getCount()
end
if getLeft() and getLeft():getId() == id then
totalItemCount = totalItemCount + getLeft():getCount()
end
if getLeg() and getLeg():getId() == id then
totalItemCount = totalItemCount + getLeg():getCount()
end
if getFeet() and getFeet():getId() == id then
totalItemCount = totalItemCount + getFeet():getCount()
end
if getFinger() and getFinger():getId() == id then
totalItemCount = totalItemCount + getFinger():getCount()
end
if getAmmo() and getAmmo():getId() == id then
totalItemCount = totalItemCount + getAmmo():getCount()
end end
return totalItemCount return totalItemCount
end end
@ -940,7 +932,7 @@ function getBestTileByPatern(pattern, specType, maxDist, safe)
if distanceFromPlayer(tile:getPosition()) <= maxDist then if distanceFromPlayer(tile:getPosition()) <= maxDist then
local minimapColor = g_map.getMinimapColor(tile:getPosition()) local minimapColor = g_map.getMinimapColor(tile:getPosition())
local stairs = (minimapColor >= 210 and minimapColor <= 213) local stairs = (minimapColor >= 210 and minimapColor <= 213)
if tile:canShoot() and tile:isWalkable() and not stairs then if tile:canShoot() and tile:isWalkable() then
if getCreaturesInArea(tile:getPosition(), pattern, specType) > 0 then if getCreaturesInArea(tile:getPosition(), pattern, specType) > 0 then
if (not safe or if (not safe or
getCreaturesInArea(tile:getPosition(), pattern, 3) == 0) then getCreaturesInArea(tile:getPosition(), pattern, 3) == 0) then
@ -969,12 +961,12 @@ function getBestTileByPatern(pattern, specType, maxDist, safe)
end end
-- returns container object based on name -- returns container object based on name
function getContainerByName(name) function getContainerByName(name, notFull)
if type(name) ~= "string" then return nil end if type(name) ~= "string" then return nil end
local d = nil local d = nil
for i, c in pairs(getContainers()) do for i, c in pairs(getContainers()) do
if c:getName():lower() == name:lower() then if c:getName():lower() == name:lower() and (not notFull or not containerIsFull(c)) then
d = c d = c
break break
end end
@ -983,12 +975,12 @@ function getContainerByName(name)
end end
-- returns container object based on container ID -- returns container object based on container ID
function getContainerByItem(id) function getContainerByItem(id, notFull)
if type(id) ~= "number" then return nil end if type(id) ~= "number" then return nil end
local d = nil local d = nil
for i, c in pairs(getContainers()) do for i, c in pairs(getContainers()) do
if c:getContainerItem():getId() == id then if c:getContainerItem():getId() == id and (not notFull or not containerIsFull(c)) then
d = c d = c
break break
end end

View File

@ -56,8 +56,8 @@ local function parseMarketEnter(protocol, msg)
end end
local balance = 0 local balance = 0
if g_game.getClientVersion() <= 1250 or not g_game.getFeature(GameTibia12Protocol) then if g_game.getProtocolVersion() <= 1250 or not g_game.getFeature(GameTibia12Protocol) then
if g_game.getClientVersion() >= 981 or g_game.getClientVersion() < 944 then if g_game.getProtocolVersion() >= 981 or g_game.getProtocolVersion() < 944 then
balance = msg:getU64() balance = msg:getU64()
else else
balance = msg:getU32() balance = msg:getU32()
@ -65,7 +65,7 @@ local function parseMarketEnter(protocol, msg)
end end
local vocation = -1 local vocation = -1
if g_game.getClientVersion() >= 944 and g_game.getClientVersion() < 950 then if g_game.getProtocolVersion() >= 944 and g_game.getProtocolVersion() < 950 then
vocation = msg:getU8() -- get vocation id vocation = msg:getU8() -- get vocation id
end end
local offers = msg:getU8() local offers = msg:getU8()
@ -100,7 +100,7 @@ local function parseMarketDetail(protocol, msg)
end end
end end
if g_game.getClientVersion() >= 1100 then -- imbuements if g_game.getProtocolVersion() >= 1100 then -- imbuements
if msg:peekU16() ~= 0x00 then if msg:peekU16() ~= 0x00 then
table.insert(descriptions, {MarketItemDescription.Last + 1, msg:getString()}) table.insert(descriptions, {MarketItemDescription.Last + 1, msg:getString()})
else else

View File

@ -124,7 +124,7 @@ function registerProtocol()
registerOpcode(ServerPackets.Inspection, function(protocol, msg) registerOpcode(ServerPackets.Inspection, function(protocol, msg)
local bool = msg:getU8() -- IsPlayer local bool = msg:getU8() -- IsPlayer
if g_game.getClientVersion() >= 1230 then if g_game.getProtocolVersion() >= 1230 then
msg:getU8() msg:getU8()
end end
local size = msg:getU8() -- List local size = msg:getU8() -- List
@ -209,7 +209,7 @@ function registerProtocol()
registerOpcode(ServerPackets.CyclopediaCharacterInfo, function(protocol, msg) registerOpcode(ServerPackets.CyclopediaCharacterInfo, function(protocol, msg)
local type = msg:getU8() local type = msg:getU8()
if g_game.getClientVersion() >= 1215 then if g_game.getProtocolVersion() >= 1215 then
local error = msg:getU8() local error = msg:getU8()
if error > 0 then if error > 0 then
-- [1] 'No data available at the moment.' -- [1] 'No data available at the moment.'
@ -232,7 +232,7 @@ function registerProtocol()
msg:getU16() -- lookTypeEx msg:getU16() -- lookTypeEx
end end
msg:getU8() -- Hide stamina msg:getU8() -- Hide stamina
if g_game.getClientVersion() >= 1220 then if g_game.getProtocolVersion() >= 1220 then
msg:getU8() -- Personal habs msg:getU8() -- Personal habs
msg:getString() -- Title msg:getString() -- Title
end end
@ -268,7 +268,7 @@ function registerProtocol()
msg:getU16() -- Base skill msg:getU16() -- Base skill
msg:getU16() -- Skill percent msg:getU16() -- Skill percent
end end
if g_game.getClientVersion() < 1215 then if g_game.getProtocolVersion() < 1215 then
msg:getU16() msg:getU16()
msg:getString() -- Player name msg:getString() -- Player name
msg:getString() -- Vocation msg:getString() -- Vocation
@ -369,7 +369,7 @@ function registerProtocol()
msg:getU8() -- Category 0 = Standard, 1 = Quest, 2 = Store msg:getU8() -- Category 0 = Standard, 1 = Quest, 2 = Store
msg:getU32() -- Is current ? then 1000 or 0 msg:getU32() -- Is current ? then 1000 or 0
end end
if g_game.getClientVersion() >= 1260 then if g_game.getProtocolVersion() >= 1260 then
msg:getU8() -- Mount lookHead msg:getU8() -- Mount lookHead
msg:getU8() -- Mount lookBody msg:getU8() -- Mount lookBody
msg:getU8() -- Mount lookLegs msg:getU8() -- Mount lookLegs
@ -532,7 +532,7 @@ function registerProtocol()
msg:getU8() -- Is updating msg:getU8() -- Is updating
msg:getU32() -- Normal coin msg:getU32() -- Normal coin
msg:getU32() -- Transferable coin msg:getU32() -- Transferable coin
if g_game.getClientVersion() >= 1220 then if g_game.getProtocolVersion() >= 1220 then
msg:getU32() -- Reserved auction coin msg:getU32() -- Reserved auction coin
msg:getU32() -- Tournament coin msg:getU32() -- Tournament coin
end end
@ -652,17 +652,17 @@ end
function readAddItem(msg) function readAddItem(msg)
msg:getU16() -- Item client ID msg:getU16() -- Item client ID
if g_game.getClientVersion() < 1150 then if g_game.getProtocolVersion() < 1150 then
msg:getU8() -- Unmarked msg:getU8() -- Unmarked
end end
local var = msg:getU8() local var = msg:getU8()
if g_game.getClientVersion() > 1150 then if g_game.getProtocolVersion() > 1150 then
if var == 1 then if var == 1 then
msg:getU32() -- Loot flag msg:getU32() -- Loot flag
end end
if g_game.getClientVersion() >= 1260 then if g_game.getProtocolVersion() >= 1260 then
local isQuiver = msg:getU8() local isQuiver = msg:getU8()
if isQuiver == 1 then if isQuiver == 1 then
msg:getU32() -- Quiver count msg:getU32() -- Quiver count

View File

@ -206,6 +206,8 @@ GameMapIgnoreCorpseCorrection = 117
GameDontCacheFiles = 118 -- doesn't work with encryption and compression GameDontCacheFiles = 118 -- doesn't work with encryption and compression
GameBigAurasCenter = 119 -- Automatic negative offset for aura bigger than 32x32 GameBigAurasCenter = 119 -- Automatic negative offset for aura bigger than 32x32
GameNewUpdateWalk = 120 -- Walk update rate dependant on FPS GameNewUpdateWalk = 120 -- Walk update rate dependant on FPS
GameNewCreatureStacking = 121 -- Ignore MAX_THINGS limit while adding to tile
GameCreaturesMana = 122 -- get mana from server for creatures other than Player
LastGameFeature = 130 LastGameFeature = 130

View File

@ -110,7 +110,7 @@ function ProtocolLogin:sendLoginPacket()
msg:addU8(1) --unknown msg:addU8(1) --unknown
msg:addU8(1) --unknown msg:addU8(1) --unknown
if g_game.getClientVersion() >= 1072 then if g_game.getProtocolVersion() >= 1072 then
msg:addString(string.format('%s %s', g_graphics.getVendor(), g_graphics.getRenderer())) msg:addString(string.format('%s %s', g_graphics.getVendor(), g_graphics.getRenderer()))
else else
msg:addString(g_graphics.getRenderer()) msg:addString(g_graphics.getRenderer())
@ -221,7 +221,7 @@ end
function ProtocolLogin:parseCharacterList(msg) function ProtocolLogin:parseCharacterList(msg)
local characters = {} local characters = {}
if g_game.getClientVersion() > 1010 then if g_game.getProtocolVersion() > 1010 then
local worlds = {} local worlds = {}
local worldsCount = msg:getU8() local worldsCount = msg:getU8()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.