Added waypoints for bot

This commit is contained in:
OTCv8
2019-11-01 03:44:56 +01:00
parent 85a7fbf0a6
commit 62ff2b1cf5
22 changed files with 865 additions and 32 deletions

View File

@@ -108,6 +108,12 @@ function UIComboBox:removeOption(text)
end
end
function UIComboBox:clear()
self.options = {}
self.currentIndex = -1
self:setText("")
end
function UIComboBox:onMousePress(mousePos, mouseButton)
local menu
if self.menuScroll then

View File

@@ -26,7 +26,13 @@ function init()
dofile("defaultconfig")
dofile("executor")
connect(g_game, { onGameStart = online, onGameEnd = offline, onTalk = botOnTalk})
connect(g_game, {
onGameStart = online,
onGameEnd = offline,
onTalk = botOnTalk,
onUse = botOnUse,
onUseWith = botOnUseWith
})
connect(rootWidget, { onKeyDown = botKeyDown,
onKeyUp = botKeyUp,
@@ -56,6 +62,9 @@ function init()
else
botConfig = botDefaultConfig
end
botConfig.configs[1].name = botDefaultConfig.configs[1].name
botConfig.configs[1].script = botDefaultConfig.configs[1].script
botButton = modules.client_topmenu.addRightGameToggleButton('botButton',
tr('Bot'), '/images/topbuttons/bot', toggle)
@@ -136,7 +145,13 @@ function terminate()
onKeyUp = botKeyUp,
onKeyPress = botKeyPress })
disconnect(g_game, { onGameStart = online, onGameEnd = offline, onTalk = botOnTalk})
disconnect(g_game, {
onGameStart = online,
onGameEnd = offline,
onTalk = botOnTalk,
onUse = botOnUse,
onUseWith = botOnUseWith
})
disconnect(Tile, { onAddThing = botAddThing, onRemoveThing = botRemoveThing })
@@ -177,7 +192,7 @@ function online()
botButton:show()
updateEnabled()
if botConfig.enabled then
scheduleEvent(refreshConfig, 1)
scheduleEvent(refreshConfig, 20)
else
clearConfig()
end
@@ -337,7 +352,7 @@ function refreshConfig()
end
errorOccured = false
g_game.enableTileThingLuaCallback(false)
local status, result = pcall(function() return executeBot(config.script, config.storage, botTabs, botMsgCallback) end)
local status, result = pcall(function() return executeBot(config.script, config.storage, botTabs, botMsgCallback, saveConfig) end)
if not status then
errorOccured = true
statusLabel:setText("Error: " .. tostring(result))
@@ -454,3 +469,13 @@ function botCraetureHealthPercentChange(creature, healthPercent)
if compiledConfig == nil then return false end
safeBotCall(function() compiledConfig.callbacks.onCreatureHealthPercentChange(creature, healthPercent) end)
end
function botOnUse(pos, itemId, stackPos, subType)
if compiledConfig == nil then return false end
safeBotCall(function() compiledConfig.callbacks.onUse(pos, itemId, stackPos, subType) end)
end
function botOnUseWith(pos, itemId, target, subType)
if compiledConfig == nil then return false end
safeBotCall(function() compiledConfig.callbacks.onUseWith(pos, itemId, target, subType) end)
end

View File

@@ -33,7 +33,16 @@ BotSeparator < HorizontalSeparator
BotPanel < Panel
layout:
type: verticalBox
CaveBotLabel < Label
background-color: alpha
text-offset: 2 0
focusable: true
$focus:
background-color: #00000033
color: #ffffff
MiniWindow
id: botWindow
!text: tr('Bot')

View File

@@ -1,41 +1,49 @@
botDefaultConfig = {
configs = {
{name = "Example", script = [=[
--Example
{name = "Default", script = [=[
--Default
--IMPORTANT
--In this config editions are not saved
--#main
Panels.Haste()
Panels.ManaShield()
Panels.Health()
Panels.HealthItem()
Panels.ManaItem()
Panels.ManaItem()
Panels.AntiParalyze()
local tab2 = addTab("Another Tab")
addButton("button1", "test button on 2nd tab", nil, tab2)
local battleTab = addTab("Battle")
local caveTab = addTab("Cave")
local toolsTab = addTab("Tools")
local tab3 = addTab("3th tab")
addLabel("label1", "Label on 3th tab", tab3)
Panels.Turning(tab3)
Panels.HealthItem(battleTab)
Panels.ManaItem(battleTab)
local waypoints = Panels.Waypoints(caveTab)
local attacking = Panels.Attacking(caveTab)
local looting = Panels.Looting(caveTab)
--#macros
local helloLabel = addLabel("helloLabel", "", tab2)
local helloLabel = addLabel("helloLabel", "")
macro(1000, "example macro (time)", nil, function()
helloLabel:setText("Time from start: " .. now)
end, tab2)
end)
macro(1000, "this macro does nothing", nil, function()
end, toolsTab)
--#hotkeys
hotkey("f5", "example hotkey", function()
info("Wow, you clicked f5 hotkey")
end)
singlehotkey("f6", "example hotkey2", function()
singlehotkey("ctrl+f6", "example hotkey2", function()
info("Wow, you clicked f6 singlehotkey")
end)
--#callbacks
local positionLabel = addLabel("positionLabel", "")
@@ -43,9 +51,6 @@ onPlayerPositionChange(function()
positionLabel:setText("Pos: " .. posx() .. "," .. posy() .. "," .. posz())
end)
listen(player:getName(), function(text)
info("you said: " .. text)
end)
--#other
HTTP.getJSON("https://api.ipify.org/?format=json", function(data, err)
@@ -53,7 +58,7 @@ HTTP.getJSON("https://api.ipify.org/?format=json", function(data, err)
warn("Whoops! Error occured: " .. err)
return
end
info("HTTP: My IP is: " .. tostring(data['ip']))
local myIp = data['ip']
end)
@@ -204,7 +209,7 @@ end)
--#callbacks
--#other
]=]},
]=]},
{}, {}, {}, {}
},
enabled = false,

View File

@@ -1,7 +1,8 @@
function executeBot(config, storage, tabs, msgCallback)
function executeBot(config, storage, tabs, msgCallback, saveConfigCallback)
local context = {}
context.tabs = tabs
context.panel = context.tabs:addTab("Main", g_ui.createWidget('BotPanel')).tabPanel
context.saveConfig = saveConfigCallback
context.storage = storage
if context.storage._macros == nil then
@@ -22,7 +23,9 @@ function executeBot(config, storage, tabs, msgCallback)
onCreatureAppear = {},
onCreatureDisappear = {},
onCreaturePositionChange = {},
onCreatureHealthPercentChange = {}
onCreatureHealthPercentChange = {},
onUse = {},
onUseWith = {}
}
-- basic functions & classes
@@ -36,6 +39,9 @@ function executeBot(config, storage, tabs, msgCallback)
context.tr = tr
context.json = json
context.regexMatch = regexMatch
context.getDistanceBetween = function(p1, p2)
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
end
-- classes
context.g_resources = g_resources
@@ -166,7 +172,17 @@ function executeBot(config, storage, tabs, msgCallback)
for i, callback in ipairs(context._callbacks.onCreatureHealthPercentChange) do
callback(creature, healthPercent)
end
end
end,
onUse = function(pos, itemId, stackPos, subType)
for i, callback in ipairs(context._callbacks.onUse) do
callback(pos, itemId, stackPos, subType)
end
end,
onUseWith = function(pos, itemId, target, subType)
for i, callback in ipairs(context._callbacks.onUseWith) do
callback(pos, itemId, target, subType)
end
end
}
}
end

View File

@@ -11,9 +11,10 @@ context.callback = function(callbackType, callback)
local callbackData = {}
table.insert(context._callbacks[callbackType], function(...)
if not callbackData.delay or callbackData.delay < context.now then
local prevExecution = context._currentExecution
context._currentExecution = callbackData
callback(...)
context._currentExecution = nil
context._currentExecution = prevExecution
end
end)
end
@@ -68,6 +69,16 @@ context.onCreatureHealthPercentChange = function(callback)
return context.callback("onCreatureHealthPercentChange", callback)
end
-- onUse(callback) -- callback = function(pos, itemId, stackPos, subType)
context.onUse = function(callback)
return context.callback("onUse", callback)
end
-- onUseWith(callback) -- callback = function(pos, itemId, target, subType)
context.onUseWith = function(callback)
return context.callback("onUseWith", callback)
end
-- custom callbacks

View File

@@ -52,7 +52,7 @@ context.macro = function(timeout, name, hotkey, callback, parent)
local macroData = context._macros[#context._macros]
macroData.callback = function()
if not macroData.delay or macroData.delay < context.now then
context._currentExecution = macroData
context._currentExecution = macroData
callback()
context._currentExecution = nil
return true

View File

@@ -36,4 +36,40 @@ context.getPlayerByName = function(name, multifloor)
end
end
return nil
end
context.findPath = function(startPos, destPos, maxDist, ignoreFields, ignoreCreatures)
if type(maxDist) ~= 'number' then
maxDist = 100
end
local complexity = math.min(10000, maxDist * maxDist)
local flags = 0
if ignoreFields then
flags = flags + 4
end
if ignoreCreatures then
flags = flags + 16
end
return g_map.findPath(startPos, destPos, complexity, flags)
end
context.autoWalk = function(destination, maxDist, ignoreFields, ignoreCreatures)
if maxDist == nil then
maxDist = 100
end
if ignoreFields == nil then
ignoreFields = false
end
if ignoreCreatures == nil then
ignoreCreatures = false
end
if context.player:getPosition().z ~= destination.z then
return false
end
local path = context.findPath(context.player:getPosition(), destination, maxDist, ignoreFields, ignoreCreatures)
if #path < 1 then
return false
end
g_game.autoWalk(path, context.player:getPosition())
return true
end

View File

@@ -54,7 +54,6 @@ end
context.changeOutfit = context.setOutfit
context.setSpeed = function(value) context.player:setSpeed(value) end
context.autoWalk = function(destination) return context.player:autoWalk(destination) end
context.walk = function(dir) return modules.game_walking.walk(dir) end
context.turn = function(dir) return g_game.turn(dir) end

View File

@@ -0,0 +1,19 @@
local context = G.botContext
local Panels = context.Panels
Panels.Attacking = function(parent)
context.setupUI([[
Panel
id: attacking
height: 150
BotLabel
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text: Attacking
]], parent)
end

View File

@@ -195,7 +195,6 @@ Panel
ui:setId(panelName)
ui.item.onItemChange = function(widget)
cp("item change")
context.storage["healthItem" .. panelId] = widget:getItemId()
end
ui.item:setItemId(context.storage["healthItem" .. panelId] or 266)

View File

@@ -0,0 +1,20 @@
local context = G.botContext
local Panels = context.Panels
Panels.Looting = function(parent)
context.setupUI([[
Panel
id: looting
height: 150
BotLabel
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text: Looting
]], parent)
end

View File

@@ -0,0 +1,575 @@
local context = G.botContext
local Panels = context.Panels
Panels.Waypoints = function(parent)
local ui = context.setupUI([[
Panel
id: waypoints
height: 213
BotLabel
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text: Waypoints
ComboBox
id: config
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 5
text-offset: 3 0
width: 130
Button
id: enableButton
anchors.top: prev.top
anchors.left: prev.right
anchors.right: parent.right
margin-left: 5
Button
margin-top: 1
id: add
anchors.top: prev.bottom
anchors.left: parent.left
text: Add
width: 60
Button
id: edit
anchors.top: prev.top
anchors.horizontalCenter: parent.horizontalCenter
text: Edit
width: 60
Button
id: remove
anchors.top: prev.top
anchors.right: parent.right
text: Remove
width: 60
TextList
id: list
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
vertical-scrollbar: listScrollbar
margin-right: 15
margin-top: 2
height: 60
focusable: false
auto-focus: first
VerticalScrollBar
id: listScrollbar
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.right: parent.right
pixels-scroll: true
step: 5
Label
id: pos
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
text-align: center
margin-top: 2
Button
id: wGoto
anchors.top: prev.bottom
anchors.left: parent.left
text: Goto
width: 61
margin-top: 1
Button
id: wUse
anchors.top: prev.top
anchors.left: prev.right
text: Use
width: 61
Button
id: wUseWith
anchors.top: prev.top
anchors.left: prev.right
text: UseWith
width: 61
Button
id: wWait
anchors.top: prev.bottom
anchors.left: parent.left
text: Wait
width: 61
margin-top: 1
Button
id: wSay
anchors.top: prev.top
anchors.left: prev.right
text: Say
width: 61
Button
id: wFunction
anchors.top: prev.top
anchors.left: prev.right
text: Function
width: 61
BotSwitch
id: recording
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
text: Auto Recording
]], parent)
if type(context.storage.cavebot) ~= "table" then
context.storage.cavebot = {}
end
if type(context.storage.cavebot.configs) ~= "table" then
context.storage.cavebot.configs = {}
end
local getConfigName = function(config)
local matches = regexMatch(config, [[name:\s*([^\n]*)$]])
if matches[1] and matches[1][2] then
return matches[1][2]:trim()
end
return nil
end
local isValidCommand = function(command)
if command == "goto" then
return true
elseif command == "use" then
return true
elseif command == "usewith" then
return true
elseif command == "wait" then
return true
elseif command == "say" then
return true
elseif command == "function" then
return true
end
return false
end
local commands = {}
local waitTo = 0
local autoRecording = false
local parseConfig = function(config)
commands = {}
local matches = regexMatch(config, [[\s*([^:^\n]+)(:?)([^\n]*)]])
for i=1,#matches do
local command = matches[i][2]
local validation = (matches[i][3] == ":")
if not validation or isValidCommand(command) then
local text = matches[i][4]
if validation then
table.insert(commands, {command=command:lower(), text=text})
elseif #commands > 0 then
commands[#commands].text = commands[#commands].text .. "\n" .. command
end
end
end
for i=1,#commands do
local label = g_ui.createWidget("CaveBotLabel", ui.list)
label:setText(commands[i].command .. ":" .. commands[i].text)
end
end
local ignoreOnOptionChange = true
local refreshConfig = function(scrollDown)
ignoreOnOptionChange = true
if context.storage.cavebot.enabled then
autoRecording = false
ui.recording:setOn(false)
ui.enableButton:setText("On")
ui.enableButton:setColor('#00AA00FF')
else
ui.enableButton:setText("Off")
ui.enableButton:setColor('#FF0000FF')
ui.recording:setOn(autoRecording)
end
ui.config:clear()
for i, config in ipairs(context.storage.cavebot.configs) do
local name = getConfigName(config)
if not name then
name = "Unnamed config"
end
ui.config:addOption(name)
end
if not context.storage.cavebot.activeConfig and #context.storage.cavebot.configs > 0 then
context.storage.cavebot.activeConfig = 1
end
ui.list:destroyChildren()
if context.storage.cavebot.activeConfig then
ui.config:setCurrentIndex(context.storage.cavebot.activeConfig)
parseConfig(context.storage.cavebot.configs[context.storage.cavebot.activeConfig])
end
context.saveConfig()
if scrollDown and ui.list:getLastChild() then
ui.list:focusChild(ui.list:getLastChild())
end
waitTo = 0
ignoreOnOptionChange = false
end
ui.config.onOptionChange = function(widget)
if not ignoreOnOptionChange then
context.storage.cavebot.activeConfig = widget.currentIndex
refreshConfig()
end
end
ui.enableButton.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
context.storage.cavebot.enabled = not context.storage.cavebot.enabled
refreshConfig()
end
ui.add.onClick = function()
modules.game_textedit.multilineEditor("Waypoints editor", "name:Config name\n", function(newText)
table.insert(context.storage.cavebot.configs, newText)
context.storage.cavebot.activeConfig = #context.storage.cavebot.configs
refreshConfig()
end)
end
ui.edit.onClick = function()
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)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = newText
refreshConfig()
end)
end
ui.remove.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
context.storage.cavebot.enabled = false
table.remove(context.storage.cavebot.configs, context.storage.cavebot.activeConfig)
context.storage.cavebot.activeConfig = 0
refreshConfig()
end
-- waypoint editor
-- auto recording
local stepsSincleLastPos = 0
context.onPlayerPositionChange(function(newPos, oldPos)
ui.pos:setText("Position: " .. newPos.x .. ", " .. newPos.y .. ", " .. newPos.z)
if not autoRecording then
return
end
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
local newText = ""
if newPos.z ~= oldPos.z then
newText = "goto:" .. oldPos.x .. "," .. oldPos.y .. "," .. oldPos.z
if #commands > 0 then
local lastCommand = commands[#commands].command .. ":" .. commands[#commands].text
if lastCommand == newText then
return
end
end
stepsSincleLastPos = 0
else
stepsSincleLastPos = stepsSincleLastPos + 1
if stepsSincleLastPos > 10 then
newText = "goto:" .. oldPos.x .. "," .. oldPos.y .. "," .. oldPos.z
stepsSincleLastPos = 0
end
end
if newText:len() > 0 then
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
refreshConfig(true)
end
end)
context.onUse(function(pos, itemId, stackPos, subType)
if not autoRecording then
return
end
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
if pos.x == 0xFFFF then
return
end
stepsSincleLastPos = 0
newText = "use:" .. pos.x .. "," .. pos.y .. "," .. pos.z
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
refreshConfig(true)
end)
context.onUseWith(function(pos, itemId, target, subType)
if not autoRecording then
return
end
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
if not target:isItem() then
return
end
local targetPos = target:getPosition()
if targetPos.x == 0xFFFF then
return
end
stepsSincleLastPos = 0
newText = "usewith:" .. itemId .. "," .. targetPos.x .. "," .. targetPos.y .. "," .. targetPos.z
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
refreshConfig(true)
end)
-- ui
local pos = context.player:getPosition()
ui.pos:setText("Position: " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
ui.wGoto.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
local pos = context.player:getPosition()
modules.game_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)
end
ui.wUse.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
local pos = context.player:getPosition()
modules.game_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)
end
ui.wUseWith.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
local pos = context.player:getPosition()
modules.game_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)
end
ui.wWait.onClick = function()
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)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nwait:" .. newText
refreshConfig(true)
end)
end
ui.wSay.onClick = function()
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)
context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nsay:" .. newText
refreshConfig(true)
end)
end
ui.wFunction.onClick = function()
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\n\n -- must return true to execute next command, othwerwise 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)
end
ui.recording.onClick = function()
if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
return
end
autoRecording = not autoRecording
if autoRecording then
context.storage.cavebot.enabled = false
stepsSincleLastPos = 10
end
refreshConfig(true)
end
refreshConfig()
local functions = {
enable = function()
context.storage.cavebot.enabled = true
refreshConfig()
end,
disable = function()
context.storage.cavebot.enabled = false
refreshConfig()
end,
refresh = function()
refreshConfig()
end
}
local executeNextMacroCall = false
local commandExecutionNo = 0
local lastGotoSuccesful = true
context.macro(250, function()
if not context.storage.cavebot.enabled then
return
end
if context.player:isWalking() then
executeNextMacroCall = false
return
end
if not executeNextMacroCall then
executeNextMacroCall = true
return
end
executeNextMacroCall = false
local commandWidget = ui.list:getFocusedChild()
if not commandWidget then
if ui.list:getFirstChild() then
ui.list:focusChild(ui.list:getFirstChild())
end
return
end
local commandIndex = ui.list:getChildIndex(commandWidget)
local command = commands[commandIndex]
if not command then
if ui.list:getFirstChild() then
ui.list:focusChild(ui.list:getFirstChild())
end
return
end
if command.command == "goto" then
local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
if #matches == 1 and #matches[1] == 4 then
local position = {x=tonumber(matches[1][2]), y=tonumber(matches[1][3]), z=tonumber(matches[1][4])}
local distance = context.getDistanceBetween(position, context.player:getPosition())
if distance > 0 and position.z == context.player:getPosition().z then
commandExecutionNo = commandExecutionNo + 1
lastGotoSuccesful = false
if commandExecutionNo <= 3 then -- try max 3 times
if not context.autoWalk(position, 100 + distance * 2, commandExecutionNo > 1, false) then
context.autoWalk(position, 100 + distance * 2, true, true)
context.delay(500)
return
end
return
elseif commandExecutionNo == 4 then -- try last time, location close to destination
position.x = position.x + math.random(-1, 1)
position.y = position.y + math.random(-1, 1)
if context.autoWalk(position, 100 + distance * 2, true) then
return
end
elseif distance < 2 then
lastGotoSuccesful = true
end
else
lastGotoSuccesful = (position.z == context.player:getPosition().z)
end
else
context.error("Waypoints: invalid use of goto function")
end
elseif command.command == "use" then
local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
if #matches == 1 and #matches[1] == 4 then
local position = {x=tonumber(matches[1][2]), y=tonumber(matches[1][3]), z=tonumber(matches[1][4])}
if context.player:getPosition().z == position.z then
local tile = g_map.getTile(position)
if tile then
local topThing = tile:getTopUseThing()
if topThing then
g_game.use(topThing)
context.delay(500)
end
end
end
else
context.error("Waypoints: invalid use of use function")
end
elseif command.command == "usewith" then
local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
if #matches == 1 and #matches[1] == 5 then
local itemId = tonumber(matches[1][2])
local position = {x=tonumber(matches[1][3]), y=tonumber(matches[1][4]), z=tonumber(matches[1][5])}
if context.player:getPosition().z == position.z then
local tile = g_map.getTile(position)
if tile then
local topThing = tile:getTopUseThing()
if topThing then
context.useWith(itemId, topThing)
context.delay(500)
end
end
end
else
context.error("Waypoints: invalid use of usewith function")
end
elseif command.command == "wait" and lastGotoSuccesful then
if not waitTo or waitTo == 0 then
waitTo = context.now + tonumber(command.text)
end
if context.now < waitTo then
return
end
waitTo = 0
elseif command.command == "say" and lastGotoSuccesful then
context.say(command.text)
elseif command.command == "function" and lastGotoSuccesful then
local status, result = pcall(function()
return assert(load("return " .. command.text, nil, nil, context))()(functions)
end)
if not status then
context.error("Waypoints function execution error:\n" .. result)
context.delay(2500)
end
if not result then
return
end
end
local nextIndex = 1 + commandIndex % #commands
local nextChild = ui.list:getChildByIndex(nextIndex)
if nextChild then
ui.list:focusChild(nextChild)
commandExecutionNo = 0
end
end)
return functions
end

View File

@@ -11,7 +11,7 @@ function updateFeatures(version)
-- you can add custom features here, list of them in modules\gamelib\const.lua
g_game.enableFeature(GameBot)
--g_game.enableFeature(GameMinimapLimitedToSingleFloor)
g_game.enableFeature(GameMinimapLimitedToSingleFloor)
--g_game.enableFeature(GameSpritesAlphaChannel)
if(version >= 770) then

View File

@@ -35,7 +35,7 @@ function init()
end
function terminate()
disconnect(g_game, { onGameEnd = hide })
disconnect(g_game, { onGameStart = check, onGameEnd = hide })
ProtocolGame.unregisterExtendedOpcode(SHOP_EXTENTED_OPCODE, onExtendedOpcode)

View File

@@ -51,6 +51,64 @@ function show(widget)
activeWindow:focus()
end
function singlelineEditor(text, callback)
if activeWindow then
destroyWindow()
end
local window = g_ui.createWidget('TextEditWindow', rootWidget)
local destroy = function()
window:destroy()
if window == activeWindow then
activeWindow = nil
end
end
window.okButton.onClick = function()
local text = window.text:getText()
destroy()
callback(text)
end
window.cancelButton.onClick = destroy
window.onEscape = destroy
window.onEnter = window.okButton.onClick
window.text:setText(text)
activeWindow = window
activeWindow:raise()
activeWindow:focus()
end
function multilineEditor(description, text, callback)
if activeWindow then
destroyWindow()
end
local window = g_ui.createWidget('TextEditMultilineWindow', rootWidget)
local destroy = function()
window:destroy()
if window == activeWindow then
activeWindow = nil
end
end
window.okButton.onClick = function()
local text = window.text:getText()
destroy()
callback(text)
end
window.cancelButton.onClick = destroy
window.onEscape = destroy
window.description:setText(description)
window.text:setText(text)
activeWindow = window
activeWindow:raise()
activeWindow:focus()
end
function hide()
destroyWindow()
end

View File

@@ -23,3 +23,51 @@ TextEditWindow < MainWindow
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 60
TextEditMultilineWindow < MainWindow
id: texteditmultiline
size: 650 497
!text: tr("Edit text")
Label
id: description
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text-auto-resize: true
text-align: center
text-wrap: true
MultilineTextEdit
id: text
anchors.top: textScroll.top
anchors.left: parent.left
anchors.right: textScroll.left
anchors.bottom: textScroll.bottom
vertical-scrollbar: textScroll
text-wrap: true
VerticalScrollBar
id: textScroll
anchors.top: description.bottom
anchors.bottom: okButton.top
anchors.right: parent.right
margin-bottom: 10
step: 16
pixels-scroll: true
Button
id: okButton
!text: tr('Ok')
anchors.bottom: parent.bottom
anchors.right: next.left
margin-right: 10
width: 60
Button
id: cancelButton
!text: tr('Cancel')
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 60

Binary file not shown.

Binary file not shown.

7
otclientv8.log Normal file
View File

@@ -0,0 +1,7 @@
GPU ANGLE (Intel(R) UHD Graphics 620 Direct3D9Ex vs_3_0 ps_3_0)
OpenGL OpenGL ES 2.0 (ANGLE 2.1.a502c749b249)
== application started at Nov 01 2019 03:27:53
OTClientV8 0.999 beta rev 0 (alpha) made by otclient.ovh built on Oct 31 2019 for arch x86
[Atlas] Texture size is: 4096x4096 (max: 8192x8192)
Login to otclient.ovh:7172
Exiting application..

Binary file not shown.

Binary file not shown.