This commit is contained in:
OTCv8
2020-06-09 18:19:20 +02:00
parent 76d6f2ce7d
commit 541e189d3f
154 changed files with 2540 additions and 1221 deletions

View File

@@ -1,70 +0,0 @@
TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority}
if player:isWalking() then
lastWalk = now
end
local config = params.config
local creature = params.creature
if g_game.getAttackingCreature() ~= creature then
g_game.attack(creature)
end
if not isLooting then -- walk only when not looting
TargetBot.Creature.walk(creature, config, targets)
end
-- attacks
local mana = player:getMana()
if config.useGroupAttack and config.groupAttackSpell:len() > 1 and mana > config.minManaGroup then
local creatures = g_map.getSpectatorsInRange(player:getPosition(), false, config.groupAttackRadius, config.groupAttackRadius)
local playersAround = false
local monsters = 0
for _, creature in ipairs(creatures) do
if not creature:isLocalPlayer() and creature:isPlayer() then
playersAround = true
elseif creature:isMonster() then
monsters = monsters + 1
end
end
if monsters >= config.groupAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
if TargetBot.sayAttackSpell(config.groupAttackSpell, config.groupAttackDelay) then
return
end
end
end
if config.useSpellAttack and config.attackSpell:len() > 1 and mana > config.minMana then
if TargetBot.sayAttackSpell(config.attackSpell, config.attackSpellDelay) then
return
end
end
if config.useRuneAttack and config.attackRune > 100 then
if TargetBot.useAttackItem(config.attackRune, 0, creature, config.attackRuneDelay) then
return
end
end
end
TargetBot.Creature.walk = function(creature, config, targets)
-- luring
if config.lure and not (config.chase and creature:getHealthPercent() < 30) then
local monsters = 0
if targets < config.lureCount then
local path = findPath(player:getPosition(), creature:getPosition(), 5, {ignoreNonPathable=true, precision=2})
if path then
return TargetBot.walkTo(creature:getPosition(), 10, {marginMin=5, marginMax=6, ignoreNonPathable=true})
end
end
end
local currentDistance = findPath(player:getPosition(), creature:getPosition(), 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true})
if config.chase and (creature:getHealthPercent() < 30 or not config.keepDistance) then
if #currentDistance > 1 then
return TargetBot.walkTo(creature:getPosition(), 10, {ignoreNonPathable=true, precision=1})
end
elseif config.keepDistance then
if #currentDistance ~= config.keepDistanceRange and #currentDistance ~= config.keepDistanceRange + 1 then
return TargetBot.walkTo(creature:getPosition(), 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1})
end
end
end

View File

@@ -21,7 +21,7 @@ end
local actionRetries = 0
local prevActionResult = true
cavebotMacro = macro(20, function()
if TargetBot and TargetBot.isActive() then
if TargetBot and TargetBot.isActive() and not TargetBot.isCaveBotActionAllowed() then
return -- target bot or looting is working, wait
end

View File

@@ -1,5 +1,5 @@
-- main tab
VERSION = "1.1"
VERSION = "1.2"
UI.Label("Config version: " .. VERSION)
@@ -14,7 +14,7 @@ UI.Button("Discord", function()
end)
UI.Button("Forum", function()
g_platform.openUrl("https://otland.net/forums/otclient.494/")
g_platform.openUrl("https://otclient.net/")
end)
UI.Button("Help & Tutorials", function()

View File

@@ -0,0 +1,112 @@
TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority}
if player:isWalking() then
lastWalk = now
end
local config = params.config
local creature = params.creature
if g_game.getAttackingCreature() ~= creature then
g_game.attack(creature)
end
if not isLooting then -- walk only when not looting
TargetBot.Creature.walk(creature, config, targets)
end
-- attacks
local mana = player:getMana()
if config.useGroupAttack and config.groupAttackSpell:len() > 1 and mana > config.minManaGroup then
local creatures = g_map.getSpectatorsInRange(player:getPosition(), false, config.groupAttackRadius, config.groupAttackRadius)
local playersAround = false
local monsters = 0
for _, creature in ipairs(creatures) do
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
playersAround = true
elseif creature:isMonster() then
monsters = monsters + 1
end
end
if monsters >= config.groupAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
if TargetBot.sayAttackSpell(config.groupAttackSpell, config.groupAttackDelay) then
return
end
end
end
if config.useGroupAttackRune and config.groupAttackRune > 100 then
local creatures = g_map.getSpectatorsInRange(creature:getPosition(), false, config.groupRuneAttackRadius, config.groupRuneAttackRadius)
local playersAround = false
local monsters = 0
for _, creature in ipairs(creatures) do
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
playersAround = true
elseif creature:isMonster() then
monsters = monsters + 1
end
end
if monsters >= config.groupRuneAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
if TargetBot.useAttackItem(config.groupAttackRune, 0, creature, config.groupRuneAttackDelay) then
return
end
end
end
if config.useSpellAttack and config.attackSpell:len() > 1 and mana > config.minMana then
if TargetBot.sayAttackSpell(config.attackSpell, config.attackSpellDelay) then
return
end
end
if config.useRuneAttack and config.attackRune > 100 then
if TargetBot.useAttackItem(config.attackRune, 0, creature, config.attackRuneDelay) then
return
end
end
end
TargetBot.Creature.walk = function(creature, config, targets)
local cpos = creature:getPosition()
local pos = player:getPosition()
-- luring
if (config.lure or config.lureCavebot) and not (config.chase and creature:getHealthPercent() < 30) then
local monsters = 0
if targets < config.lureCount then
if config.lureCavebot then
return TargetBot.allowCaveBot(200)
else
local path = findPath(pos, cpos, 5, {ignoreNonPathable=true, precision=2})
if path then
return TargetBot.walkTo(cpos, 10, {marginMin=5, marginMax=6, ignoreNonPathable=true})
end
end
end
end
local currentDistance = findPath(pos, cpos, 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true})
if config.chase and (creature:getHealthPercent() < 30 or not config.keepDistance) then
if #currentDistance > 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1})
end
elseif config.keepDistance then
if #currentDistance ~= config.keepDistanceRange and #currentDistance ~= config.keepDistanceRange + 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1})
end
end
if config.avoidAttacks then
local diffx = cpos.x - pos.x
local diffy = cpos.y - pos.y
local candidates = {}
if math.abs(diffx) == 1 and diffy == 0 then
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x, y=pos.y+1, z=pos.z}}
elseif diffx == 0 and math.abs(diffy) == 1 then
candidates = {{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z}}
end
for _, candidate in ipairs(candidates) do
local tile = g_map.getTile(candidate)
if tile and tile:isWalkable() then
return TargetBot.walkTo(candidate, 2, {ignoreNonPathable=true})
end
end
end
end

View File

@@ -82,18 +82,24 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
addScrollBar("groupAttackRadius", "Radius of group attack spell", 1, 7, 1)
addScrollBar("groupAttackDelay", "Group attack spell delay", 200, 60000, 5000)
addScrollBar("runeAttackDelay", "Rune attack delay", 200, 5000, 2000)
addScrollBar("groupRuneAttackTargets", "Min. targets for group rune attack", 1, 10, 2)
addScrollBar("groupRuneAttackRadius", "Radius of group rune attack", 1, 7, 1)
addScrollBar("groupRuneAttackDelay", "Group rune attack delay", 200, 60000, 5000)
addCheckBox("chase", "Chase", true)
addCheckBox("keepDistance", "Keep Distance", false)
addCheckBox("lure", "Lure", false)
-- addCheckBox("avoidAttacks", "Avoid attacks", true)
addCheckBox("lureCavebot", "Lure using cavebot", false)
addCheckBox("avoidAttacks", "Avoid wave attacks", false)
addCheckBox("useSpellAttack", "Use attack spell", false)
addTextEdit("attackSpell", "Attack spell", "")
addCheckBox("useGroupAttack", "Use group attack spell", false)
addCheckBox("groupAttackIgnorePlayers", "Ignore players in group attack", false)
addTextEdit("groupAttackSpell", "Group attack spell", "")
addCheckBox("useRuneAttack", "Use attack rune", false)
addItem("attackRune", "Attack rune:", 0)
addCheckBox("useGroupAttack", "Use group attack spell", false)
addTextEdit("groupAttackSpell", "Group attack spell", "")
addCheckBox("useGroupAttackRune", "Use group attack rune", false)
addItem("groupAttackRune", "Group attack rune:", 0)
addCheckBox("groupAttackIgnorePlayers", "Ignore players in group attack", false)
addCheckBox("groupAttackIgnoreParty", "Ignore party in group attack", false)
end

View File

@@ -1,6 +1,6 @@
TargetBotCreatureEditorScrollBar < Panel
height: 35
margin-top: 7
height: 28
margin-top: 3
Label
id: text
@@ -14,7 +14,7 @@ TargetBotCreatureEditorScrollBar < Panel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-top: 3
minimum: 0
maximum: 10
step: 1
@@ -64,7 +64,7 @@ TargetBotCreatureEditorCheckBox < BotSwitch
TargetBotCreatureEditorWindow < MainWindow
text: TargetBot creature editor
width: 500
height: 650
height: 600
Label
anchors.left: parent.left

View File

@@ -145,14 +145,14 @@ TargetBot.Looting.process = function(targets, dangerLevel)
end
local container = tile:getTopUseThing()
if not container or container:getId() ~= loot.container then
if not container or not container:isContainer() then
table.remove(TargetBot.Looting.list, 1)
return true
end
g_game.open(container)
waitTill = now + 1000 -- give it 1s to open
waitingForContainer = loot.container
waitingForContainer = container:getId()
loot.tries = loot.tries + 10
return true
@@ -213,9 +213,9 @@ TargetBot.Looting.lootContainer = function(lootContainers, container)
-- loot items
local nextContainer = nil
for i, item in ipairs(container:getItems()) do
if item:isContainer() then
if item:isContainer() and not itemsById[item:getId()] then
nextContainer = item
elseif itemsById[item:getId()] or ui.everyItem:isOn() then
elseif itemsById[item:getId()] or (ui.everyItem:isOn() and not item:isContainer()) then
item.lootTries = (item.lootTries or 0) + 1
if item.lootTries < 5 then -- if can't be looted within 0.5s then skip it
return TargetBot.Looting.lootItem(lootContainers, item)

View File

@@ -1,6 +1,7 @@
local targetbotMacro = nil
local config = nil
local lastAction = 0
local cavebotAllowance = 0
-- ui
local configWidget = UI.Config()
@@ -72,6 +73,8 @@ targetbotMacro = macro(100, function()
TargetBot.Creature.attack(highestPriorityParams, targets, looting)
if lootingStatus:len() > 0 then
TargetBot.setStatus("Attack & " .. lootingStatus)
elseif cavebotAllowance > now then
TargetBot.setStatus("Luring using CaveBot")
else
TargetBot.setStatus("Attacking")
end
@@ -148,6 +151,10 @@ TargetBot.isActive = function() -- return true if attacking or looting takes pla
return lastAction + 300 > now
end
TargetBot.isCaveBotActionAllowed = function()
return cavebotAllowance > now
end
TargetBot.setStatus = function(text)
return ui.status.right:setText(text)
end
@@ -187,6 +194,10 @@ TargetBot.save = function()
config.save(data)
end
TargetBot.allowCaveBot = function(time)
cavebotAllowance = now + time
end
-- attacks
local lastSpell = 0
local lastAttackSpell = 0

View File

@@ -72,6 +72,42 @@ macro(1000, "Stack items", function()
end
end)
macro(10000, "Anti Kick", function()
local dir = player:getDirection()
turn((dir + 1) % 4)
turn(dir)
end)
UI.Separator()
UI.Label("Drop items:")
if type(storage.dropItems) ~= "table" then
storage.dropItems = {283, 284, 285}
end
local foodContainer = UI.Container(function(widget, items)
storage.dropItems = items
end, true)
foodContainer:setHeight(35)
foodContainer:setItems(storage.dropItems)
macro(5000, "drop items", function()
if not storage.dropItems[1] then return end
if TargetBot and TargetBot.isActive() then return end -- pause when attacking
for _, container in pairs(g_game.getContainers()) do
for __, item in ipairs(container:getItems()) do
for i, dropItem in ipairs(storage.dropItems) do
if item:getId() == dropItem.id then
if item:isStackable() then
return g_game.move(item, player:getPosition(), item:getCount())
else
return g_game.move(item, player:getPosition(), dropItem.count) -- count is also subtype
end
end
end
end
end
end)
UI.Separator()
UI.Label("Mana training")
@@ -80,6 +116,7 @@ if type(storage.manaTrain) ~= "table" then
end
local manatrainmacro = macro(1000, function()
if TargetBot and TargetBot.isActive() then return end -- pause when attacking
local mana = math.min(100, math.floor(100 * (player:getMana() / player:getMaxMana())))
if storage.manaTrain.max >= mana and mana >= storage.manaTrain.min then
say(storage.manaTrain.text)

View File

@@ -81,6 +81,7 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, relo
context.gcinfo = gcinfo
context.tr = tr
context.json = json
context.base64 = base64
context.regexMatch = regexMatch
context.getDistanceBetween = function(p1, p2)
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))

View File

@@ -1,5 +1,7 @@
local context = G.botContext
context.getMapView = function() return modules.game_interface.getMapPanel() end
context.getMapPanel = context.getMapView
context.zoomIn = function() modules.game_interface.getMapPanel():zoomIn() end
context.zoomOut = function() modules.game_interface.getMapPanel():zoomOut() end

View File

@@ -80,7 +80,7 @@ UI.Container = function(callback, unique, parent, widget)
for i, child in ipairs(widget.items:getChildren()) do
if child:getItemId() >= 100 then
if not duplicates[child:getItemId()] or not unique then
table.insert(items, {id=child:getItemId(), count=child:getItemCount()})
table.insert(items, {id=child:getItemId(), count=child:getItemCountOrSubType()})
duplicates[child:getItemId()] = true
end
end

View File

@@ -14,7 +14,7 @@ UI.EditorWindow = function(text, options, callback)
validation = text (regex)
examples = {{name, text}, {name, text}}
]]--
local window = modules.game_textedit.edit(text, options, callback)
local window = modules.client_textedit.edit(text, options, callback)
window.botWidget = true
return window
end

View File

@@ -679,7 +679,7 @@ Panel
refreshConfig()
end
ui.add.onClick = function()
modules.game_textedit.multilineEditor("Target list editor", "name:Config name", function(newText)
modules.client_textedit.multilineEditor("Target list editor", "name:Config name", function(newText)
table.insert(context.storage.attacking.configs, newText)
context.storage.attacking.activeConfig = #context.storage.attacking.configs
refreshConfig()
@@ -689,7 +689,7 @@ Panel
if not context.storage.attacking.activeConfig or not context.storage.attacking.configs[context.storage.attacking.activeConfig] then
return
end
modules.game_textedit.multilineEditor("Target list editor", context.storage.attacking.configs[context.storage.attacking.activeConfig], function(newText)
modules.client_textedit.multilineEditor("Target list editor", context.storage.attacking.configs[context.storage.attacking.activeConfig], function(newText)
context.storage.attacking.configs[context.storage.attacking.activeConfig] = newText
refreshConfig()
end)

View File

@@ -266,7 +266,7 @@ Panel
refreshConfig()
end
ui.add.onClick = function()
modules.game_textedit.multilineEditor("Looting editor", "name:Config name", function(newText)
modules.client_textedit.multilineEditor("Looting editor", "name:Config name", function(newText)
table.insert(context.storage.looting.configs, newText)
context.storage.looting.activeConfig = #context.storage.looting.configs
refreshConfig()
@@ -276,7 +276,7 @@ Panel
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
return
end
modules.game_textedit.multilineEditor("Looting editor", context.storage.looting.configs[context.storage.looting.activeConfig], function(newText)
modules.client_textedit.multilineEditor("Looting editor", context.storage.looting.configs[context.storage.looting.activeConfig], function(newText)
context.storage.looting.configs[context.storage.looting.activeConfig] = newText
refreshConfig()
end)

View File

@@ -312,7 +312,7 @@ Panel
end
end
ui.add.onClick = function()
modules.game_textedit.multilineEditor("Waypoints editor", "name:Config name\nlabel:start\n", function(newText)
modules.client_textedit.multilineEditor("Waypoints editor", "name:Config name\nlabel:start\n", function(newText)
table.insert(context.storage.cavebot.configs, newText)
context.storage.cavebot.activeConfig = #context.storage.cavebot.configs
refreshConfig()
@@ -322,7 +322,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.multilineEditor("Waypoints editor", context.storage.cavebot.configs[context.storage.cavebot.activeConfig], function(newText)
modules.client_textedit.multilineEditor("Waypoints editor", context.storage.cavebot.configs[context.storage.cavebot.activeConfig], function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = newText
refreshConfig()
end)
@@ -428,7 +428,7 @@ Panel
return
end
local pos = context.player:getPosition()
modules.game_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
modules.client_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\ngoto:" .. newText
refreshConfig(true)
end)
@@ -439,7 +439,7 @@ Panel
return
end
local pos = context.player:getPosition()
modules.game_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
modules.client_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nuse:" .. newText
refreshConfig(true)
end)
@@ -450,7 +450,7 @@ Panel
return
end
local pos = context.player:getPosition()
modules.game_textedit.singlelineEditor("ITEMID," .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
modules.client_textedit.singlelineEditor("ITEMID," .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nusewith:" .. newText
refreshConfig(true)
end)
@@ -460,7 +460,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.singlelineEditor("1000", function(newText)
modules.client_textedit.singlelineEditor("1000", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nwait:" .. newText
refreshConfig(true)
end)
@@ -470,7 +470,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.singlelineEditor("text", function(newText)
modules.client_textedit.singlelineEditor("text", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nsay:" .. newText
refreshConfig(true)
end)
@@ -480,7 +480,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.singlelineEditor("text", function(newText)
modules.client_textedit.singlelineEditor("text", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nnpc:" .. newText
refreshConfig(true)
end)
@@ -490,7 +490,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.singlelineEditor("label name", function(newText)
modules.client_textedit.singlelineEditor("label name", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nlabel:" .. newText
refreshConfig(true)
end)
@@ -500,7 +500,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.singlelineEditor("creature name", function(newText)
modules.client_textedit.singlelineEditor("creature name", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nfollow:" .. newText
refreshConfig(true)
end)
@@ -510,7 +510,7 @@ Panel
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
modules.game_textedit.multilineEditor("Add function", "function(waypoints)\n -- your lua code, function is executed if previous goto was successful or is just after label\n\n -- must return true to execute next command, otherwise will run in loop till correct return\n return true\nend", function(newText)
modules.client_textedit.multilineEditor("Add function", "function(waypoints)\n -- your lua code, function is executed if previous goto was successful or is just after label\n\n -- must return true to execute next command, otherwise will run in loop till correct return\n return true\nend", function(newText)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nfunction:" .. newText
refreshConfig(true)
end)

View File

@@ -29,7 +29,7 @@ BotItem < Item
&editable: true
BotTextEdit < TextEdit
@onClick: modules.game_textedit.show(self)
@onClick: modules.client_textedit.show(self)
text-align: center
multiline: false
focusable: false
@@ -52,6 +52,8 @@ BotPanel < Panel
vertical-scrollbar: botPanelScroll
layout:
type: verticalBox
$mobile:
margin-right: 16
BotSmallScrollBar
id: botPanelScroll

View File

@@ -22,7 +22,6 @@ BotIcon < UIWidget
margin-top: 0
size: 48 48
phantom: true
optimized: true
UIWidget
id: status