mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-19 06:03:27 +02:00
Version 1.8
This commit is contained in:
@@ -23,6 +23,7 @@ function init()
|
||||
g_ui.importStyle("ui/basic.otui")
|
||||
g_ui.importStyle("ui/panels.otui")
|
||||
g_ui.importStyle("ui/config.otui")
|
||||
g_ui.importStyle("ui/icons.otui")
|
||||
|
||||
connect(g_game, {
|
||||
onGameStart = online,
|
||||
@@ -89,14 +90,19 @@ function clear()
|
||||
|
||||
for i, socket in pairs(botWebSockets) do
|
||||
g_http.cancel(socket)
|
||||
botWebSockets[i] = nil
|
||||
end
|
||||
botWebSockets = {}
|
||||
|
||||
for i, widget in pairs(g_ui.getRootWidget():getChildren()) do
|
||||
if widget.botWidget then
|
||||
widget:destroy()
|
||||
end
|
||||
end
|
||||
for i, widget in pairs(modules.game_interface.gameMapPanel:getChildren()) do
|
||||
if widget.botWidget then
|
||||
widget:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local gameMapPanel = modules.game_interface.getMapPanel()
|
||||
if gameMapPanel then
|
||||
@@ -149,7 +155,8 @@ function refresh()
|
||||
end
|
||||
configList:setCurrentOption(settings[index].config)
|
||||
if configList:getCurrentOption().text ~= settings[index].config then
|
||||
settings[index].enabled = false
|
||||
settings[index].config = configList:getCurrentOption().text
|
||||
settings[index].enabled = false
|
||||
end
|
||||
|
||||
enableButton:setOn(settings[index].enabled)
|
||||
|
@@ -1,75 +0,0 @@
|
||||
ConfigTabBar < MoveableTabBar
|
||||
height: 22
|
||||
|
||||
ConfigTabBarButton < MoveableTabBarButton
|
||||
height: 22
|
||||
padding: 15
|
||||
|
||||
ConfigTabBarPanel < MoveableTabBarPanel
|
||||
|
||||
MainWindow
|
||||
id: configWindow
|
||||
size: 650 497
|
||||
!text: tr("Config editor")
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-auto-resize: true
|
||||
text-align: left
|
||||
text-wrap: true
|
||||
!text: tr("For more informations how to edit config, click 'Documentation' button")
|
||||
|
||||
ConfigTabBar
|
||||
id: configTab
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
tab-spacing: 2
|
||||
movable: false
|
||||
|
||||
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: configTab.bottom
|
||||
anchors.bottom: okButton.top
|
||||
anchors.right: parent.right
|
||||
margin-bottom: 10
|
||||
step: 16
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: documentationButton
|
||||
!text: tr('Documentation')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: 150
|
||||
@onClick: scheduleEvent(function() g_platform.openUrl("https://github.com/OTCv8/otclientv8_bot") end, 50)
|
||||
|
||||
Button
|
||||
id: okButton
|
||||
!text: tr('Ok')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
@onClick: modules.game_bot.saveEditedConfig()
|
||||
|
||||
Button
|
||||
id: cancelButton
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
@onClick: self:getParent():hide()
|
38
modules/game_bot/default_config/icons.lua
Normal file
38
modules/game_bot/default_config/icons.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
addIcon("dancing", {outfit={mount=0,feet=0,legs=0,body=176,type=128,auxType=0,addons=3,head=48}, hotkey="F5", text="dance"}, macro(100, "dance", function()
|
||||
turn(math.random(0,3))
|
||||
end))
|
||||
|
||||
addIcon("ctrl", {outfit={mount=0,feet=10,legs=10,body=176,type=129,auxType=0,addons=3,head=48}, text="press ctrl to move icon"}, function(widget, enabled)
|
||||
if enabled then
|
||||
info("icon on")
|
||||
else
|
||||
info("icon off")
|
||||
end
|
||||
end)
|
||||
|
||||
addIcon("mount", {outfit={mount=848,feet=10,legs=10,body=176,type=129,auxType=0,addons=3,head=48}}, function(widget, enabled)
|
||||
if enabled then
|
||||
info("icon mount on")
|
||||
else
|
||||
info("icon mount off")
|
||||
end
|
||||
end)
|
||||
|
||||
addIcon("mount 2", {outfit={mount=849,feet=10,legs=10,body=176,type=140,auxType=0,addons=3,head=48}, switchable=false}, function(widget, enabled)
|
||||
info("icon mount 2 pressed")
|
||||
end)
|
||||
|
||||
addIcon("item", {item=3380, hotkey="F6", switchable=false}, function(widget, enabled)
|
||||
info("icon clicked")
|
||||
end)
|
||||
|
||||
addIcon("item2", {item={id=3043, count=100}, switchable=true}, function(widget, enabled)
|
||||
info("icon 2 clicked")
|
||||
end)
|
||||
|
||||
addIcon("text", {text="text\nonly\nicon", switchable=true}, function(widget, enabled)
|
||||
info("icon with text clicked")
|
||||
end)
|
||||
|
@@ -1,305 +0,0 @@
|
||||
botDefaultConfig = {
|
||||
configs = {
|
||||
{name = "Default", script = [=[
|
||||
--Default
|
||||
--IMPORTANT
|
||||
--In 1st config (default) editions are not saved, just select and edit other config
|
||||
|
||||
--#main
|
||||
|
||||
--#panels
|
||||
|
||||
local healTab = addTab("HP")
|
||||
local batTab = addTab("Batt")
|
||||
local caveTab = addTab("Cave")
|
||||
local toolsTab = addTab("Tools")
|
||||
|
||||
Panels.TradeMessage()
|
||||
Panels.AutoStackItems()
|
||||
|
||||
addButton("discord", "Discord & Help", function()
|
||||
g_platform.openUrl("https://discord.gg/yhqBE4A")
|
||||
end)
|
||||
|
||||
addButton("forum", "Forum", function()
|
||||
g_platform.openUrl("https://otland.net/forums/otclient.494/")
|
||||
end)
|
||||
|
||||
addButton("github", "Documentation", function()
|
||||
g_platform.openUrl("https://github.com/OTCv8/otclientv8_bot")
|
||||
end)
|
||||
|
||||
addSeparator("sep")
|
||||
|
||||
Panels.Haste(healTab)
|
||||
Panels.ManaShield(healTab)
|
||||
Panels.AntiParalyze(healTab)
|
||||
Panels.Health(healTab)
|
||||
Panels.Health(healTab)
|
||||
Panels.HealthItem(healTab)
|
||||
Panels.HealthItem(healTab)
|
||||
Panels.ManaItem(healTab)
|
||||
Panels.ManaItem(healTab)
|
||||
Panels.Equip(healTab)
|
||||
Panels.Equip(healTab)
|
||||
Panels.Equip(healTab)
|
||||
Panels.Eating(healTab)
|
||||
|
||||
Panels.AttackSpell(batTab)
|
||||
Panels.AttackItem(batTab)
|
||||
|
||||
Panels.AttackLeaderTarget(batTab)
|
||||
Panels.LimitFloor(batTab)
|
||||
Panels.AntiPush(batTab)
|
||||
|
||||
local waypoints = Panels.Waypoints(caveTab)
|
||||
local attacking = Panels.Attacking(caveTab)
|
||||
local looting = Panels.Looting(caveTab)
|
||||
addButton("tutorial", "Help & Tutorials", function()
|
||||
g_platform.openUrl("https://github.com/OTCv8/otclientv8_bot")
|
||||
end, caveTab)
|
||||
|
||||
--#macros
|
||||
|
||||
macro(1000, "exchange money", function()
|
||||
local containers = getContainers()
|
||||
for i, container in pairs(containers) do
|
||||
for j, item in ipairs(container:getItems()) do
|
||||
if item:isStackable() and (item:getId() == 3035 or item:getId() == 3031) and item:getCount() == 100 then
|
||||
g_game.use(item)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
macro(1000, "this macro does nothing", "f7", function()
|
||||
|
||||
end)
|
||||
|
||||
macro(100, "debug pathfinding", nil, function()
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
tile:setText("")
|
||||
end
|
||||
local path = findEveryPath(pos(), 20, {
|
||||
ignoreNonPathable = false
|
||||
})
|
||||
local total = 0
|
||||
for i, p in pairs(path) do
|
||||
local s = i:split(",")
|
||||
local pos = {x=tonumber(s[1]), y=tonumber(s[2]), z=tonumber(s[3])}
|
||||
local tile = g_map.getTile(pos)
|
||||
if tile then
|
||||
tile:setText(p[2])
|
||||
end
|
||||
total = total + 1
|
||||
end
|
||||
end)
|
||||
|
||||
macro(1000, "speed hack", nil, function()
|
||||
player:setSpeed(1000)
|
||||
end)
|
||||
|
||||
|
||||
--#hotkeys
|
||||
|
||||
hotkey("f5", "example hotkey", function()
|
||||
info("Wow, you clicked f5 hotkey")
|
||||
end)
|
||||
|
||||
singlehotkey("ctrl+f6", "singlehotkey", function()
|
||||
info("Wow, you clicked f6 singlehotkey")
|
||||
usewith(268, player)
|
||||
end)
|
||||
|
||||
singlehotkey("ctrl+f8", "play alarm", function()
|
||||
playAlarm()
|
||||
end)
|
||||
|
||||
singlehotkey("ctrl+f9", "stop alarm", function()
|
||||
stopSound()
|
||||
end)
|
||||
|
||||
--#callbacks
|
||||
|
||||
local positionLabel = addLabel("positionLabel", "")
|
||||
onPlayerPositionChange(function()
|
||||
positionLabel:setText("Pos: " .. posx() .. "," .. posy() .. "," .. posz())
|
||||
end)
|
||||
|
||||
local s = addSwitch("sdSound", "Play sound when using sd", function(widget)
|
||||
storage.sdSound = not storage.sdSound
|
||||
widget:setOn(storage.sdSound)
|
||||
end)
|
||||
s:setOn(storage.sdSound)
|
||||
|
||||
onUseWith(function(pos, itemId)
|
||||
if storage.sdSound and itemId == 3155 then
|
||||
playSound("/sounds/magnum.ogg")
|
||||
end
|
||||
end)
|
||||
|
||||
--#other
|
||||
|
||||
macro(100, "hide useless tiles", "", function()
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if not tile:isWalkable(true) then
|
||||
tile:setFill('black')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
addLabel("mapinfo", "You can use ctrl + plus and ctrl + minus to zoom in / zoom out map")
|
||||
|
||||
]=]},
|
||||
{name = "UI & Healing", script = [=[
|
||||
-- UI & healing
|
||||
info("Tested on 10.99")
|
||||
|
||||
--#main
|
||||
local healthPanel = setupUI([[
|
||||
Panel
|
||||
id: healingPanel
|
||||
height: 150
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: Use item if
|
||||
text-align: center
|
||||
|
||||
BotItem
|
||||
id: item1
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin: 0 5 0 5
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll1
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
BotItem
|
||||
id: item2
|
||||
anchors.left: parent.left
|
||||
anchors.top: item1.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin: 0 5 0 5
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll2
|
||||
anchors.left: label2.left
|
||||
anchors.right: label2.horizontalCenter
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll3
|
||||
anchors.left: label2.horizontalCenter
|
||||
anchors.right: label2.right
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
Label
|
||||
anchors.top: item2.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
text: Drag item to change it
|
||||
text-align: center
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
]])
|
||||
|
||||
healthPanel.item1:setItemId(storage.healItem1 or 266)
|
||||
healthPanel.item1.onItemChange = function(widget, item)
|
||||
storage.healItem1 = item:getId()
|
||||
widget:setItemId(storage.healItem1)
|
||||
end
|
||||
|
||||
healthPanel.item2:setItemId(storage.healItem2 or 268)
|
||||
healthPanel.item2.onItemChange = function(widget, item)
|
||||
storage.healItem2 = item:getId()
|
||||
widget:setItemId(storage.healItem2)
|
||||
end
|
||||
|
||||
healthPanel.scroll1.onValueChange = function(scroll, value)
|
||||
storage.healPercent1 = value
|
||||
healthPanel.label1:setText("0% <= hp <= " .. storage.healPercent1 .. "%")
|
||||
end
|
||||
healthPanel.scroll1:setValue(storage.healPercent1 or 50)
|
||||
|
||||
healthPanel.scroll2.onValueChange = function(scroll, value)
|
||||
storage.healPercent2 = value
|
||||
healthPanel.label2:setText("" .. storage.healPercent2 .. "% <= mana <= " .. storage.healPercent3 .. "%")
|
||||
end
|
||||
healthPanel.scroll3.onValueChange = function(scroll, value)
|
||||
storage.healPercent3 = value
|
||||
healthPanel.label2:setText("" .. storage.healPercent2 .. "% <= mana <= " .. storage.healPercent3 .. "%")
|
||||
end
|
||||
healthPanel.scroll2:setValue(storage.healPercent2 or 40)
|
||||
healthPanel.scroll3:setValue(storage.healPercent3 or 60)
|
||||
|
||||
macro(25, function()
|
||||
if not storage.healItem1 then
|
||||
return
|
||||
end
|
||||
if healthPanel.scroll1:getValue() >= hppercent() then
|
||||
useWith(storage.healItem1, player)
|
||||
delay(500)
|
||||
end
|
||||
end)
|
||||
macro(25, function()
|
||||
if not storage.healItem2 then
|
||||
return
|
||||
end
|
||||
if storage.healPercent2 <= manapercent() and manapercent() <= storage.healPercent3 then
|
||||
useWith(storage.healItem2, player)
|
||||
delay(500)
|
||||
end
|
||||
end)
|
||||
|
||||
--#macros
|
||||
|
||||
--#hotkeys
|
||||
|
||||
--#callbacks
|
||||
|
||||
--#other
|
||||
]=]},
|
||||
{}, {}, {}, {}
|
||||
},
|
||||
enabled = false,
|
||||
selectedConfig = 1
|
||||
}
|
@@ -82,34 +82,42 @@ MainWindow
|
||||
!text: tr("To reload configs just press On and Off in bot window.\nTo learn more about bot click Tutorials button.")
|
||||
|
||||
Button
|
||||
!text: tr('Tutorials')
|
||||
!text: tr('Documentation')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: 100
|
||||
width: 118
|
||||
@onClick: g_platform.openUrl("http://otclient.ovh/bot.php?documentation")
|
||||
|
||||
Button
|
||||
!text: tr('Tutorials')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
width: 80
|
||||
@onClick: g_platform.openUrl("http://otclient.ovh/bot.php?tutorials")
|
||||
|
||||
Button
|
||||
!text: tr('Scripts')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
margin-left: 5
|
||||
width: 80
|
||||
@onClick: g_platform.openUrl("http://otclient.ovh/bot.php?scripts")
|
||||
|
||||
Button
|
||||
!text: tr('Forum')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
margin-left: 5
|
||||
width: 80
|
||||
@onClick: g_platform.openUrl("http://otclient.ovh/bot.php?forum")
|
||||
|
||||
Button
|
||||
!text: tr('Discord')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
margin-left: 5
|
||||
width: 80
|
||||
@onClick: g_platform.openUrl("http://otclient.ovh/bot.php?discord")
|
||||
|
||||
Button
|
||||
|
@@ -30,7 +30,7 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
|
||||
context.storage._macros = {} -- active macros
|
||||
end
|
||||
|
||||
-- macros, hotkeys, scheduler, callbacks
|
||||
-- macros, hotkeys, scheduler, icons, callbacks
|
||||
context._macros = {}
|
||||
context._hotkeys = {}
|
||||
context._scheduler = {}
|
||||
@@ -123,9 +123,9 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
|
||||
context.time = g_clock.millis()
|
||||
|
||||
for i, macro in ipairs(context._macros) do
|
||||
if macro.lastExecution + macro.timeout <= context.now and (macro.name == nil or macro.name:len() < 1 or context.storage._macros[macro.name]) then
|
||||
if macro.lastExecution + macro.timeout <= context.now and (macro.name == nil or macro.name:len() < 1 or macro.enabled) then
|
||||
local status, result = pcall(function()
|
||||
if macro.callback() then
|
||||
if macro.callback(macro) then
|
||||
macro.lastExecution = context.now
|
||||
end
|
||||
end)
|
||||
|
@@ -1,123 +0,0 @@
|
||||
-- In this file are declared extra functions and variables for bot
|
||||
-- It has been made to make most common functions shorter, for eg. hp() instead of player:getHealth()
|
||||
|
||||
function setupFunctions(context)
|
||||
-- player releated
|
||||
context.name = function() return context.player:getName() end
|
||||
|
||||
context.hp = function() return context.player:getHealth() end
|
||||
context.mana = function() return context.player:getMana() end
|
||||
context.hppercent = function() return context.player:getHealthPercent() end
|
||||
context.manapercent = function() if context.player:getMaxMana() <= 1 then return 100 else return math.floor(context.player:getMana() * 100 / context.player:getMaxMana()) end end
|
||||
context.maxhp = function() return context.player:getMaxHealth() end
|
||||
context.maxmana = function() return context.player:getMaxMana() end
|
||||
context.hpmax = function() return context.player:getMaxHealth() end
|
||||
context.manamax = function() return context.player:getMaxMana() end
|
||||
|
||||
context.cap = function() return context.player:getCapacity() end
|
||||
context.freecap = function() return context.player:getFreeCapacity() end
|
||||
context.maxcap = function() return context.player:getTotalCapacity() end
|
||||
context.capmax = function() return context.player:getTotalCapacity() end
|
||||
|
||||
context.exp = function() return context.player:getExperience() end
|
||||
context.lvl = function() return context.player:getLevel() end
|
||||
context.level = function() return context.player:getLevel() end
|
||||
|
||||
context.mlev = function() return context.player:getMagicLevel() end
|
||||
context.magic = function() return context.player:getMagicLevel() end
|
||||
context.mlevel = function() return context.player:getMagicLevel() end
|
||||
|
||||
context.soul = function() return context.player:getSoul() end
|
||||
context.stamina = function() return context.player:getStamina() end
|
||||
context.voc = function() return context.player:getVocation() end
|
||||
context.vocation = function() return context.player:getVocation() end
|
||||
|
||||
context.bless = function() return context.player:getBlessings() end
|
||||
context.blesses = function() return context.player:getBlessings() end
|
||||
context.blessings = function() return context.player:getBlessings() end
|
||||
|
||||
|
||||
context.pos = function() return context.player:getPosition() end
|
||||
context.posx = function() return context.player:getPosition().x end
|
||||
context.posy = function() return context.player:getPosition().y end
|
||||
context.posz = function() return context.player:getPosition().z end
|
||||
|
||||
context.direction = function() return context.player:getDirection() end
|
||||
context.speed = function() return context.player:getSpeed() end
|
||||
context.skull = function() return context.player:getSkull() end
|
||||
context.outfit = function() return context.player:getOutfit() end
|
||||
|
||||
context.setOutfit = function(outfit)
|
||||
modules.game_outfit.ignoreNextOutfitWindow = g_clock.millis()
|
||||
g_game.requestOutfit()
|
||||
context.schedule(100, function()
|
||||
g_game.changeOutfit(outfit)
|
||||
end)
|
||||
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
|
||||
|
||||
-- game releated
|
||||
context.say = g_game.talk
|
||||
context.talk = g_game.talk
|
||||
context.talkPrivate = g_game.talkPrivate
|
||||
context.sayPrivate = g_game.talkPrivate
|
||||
context.use = g_game.useInventoryItem
|
||||
context.usewith = g_game.useInventoryItemWith
|
||||
context.useWith = g_game.useInventoryItemWith
|
||||
context.findItem = g_game.findItemInContainers
|
||||
|
||||
context.attack = g_game.attack
|
||||
context.cancelAttack = g_game.cancelAttack
|
||||
context.follow = g_game.follow
|
||||
context.cancelFollow = g_game.cancelFollow
|
||||
context.cancelAttackAndFollow = g_game.cancelAttackAndFollow
|
||||
|
||||
context.logout = g_game.forceLogout
|
||||
context.ping = g_game.getPing
|
||||
|
||||
-- map releated
|
||||
context.zoomIn = function() modules.game_interface.getMapPanel():zoomIn() end
|
||||
context.zoomOut = function() modules.game_interface.getMapPanel():zoomOut() end
|
||||
|
||||
context.getSpectators = function(multifloor)
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
return g_map.getSpectators(context.player:getPosition(), multifloor)
|
||||
end
|
||||
|
||||
context.getCreatureByName = function(name, multifloor)
|
||||
if not name then return nil end
|
||||
name = name:lower()
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
for i, spec in ipairs(g_map.getSpectators(context.player:getPosition(), multifloor)) do
|
||||
if spec:getName():lower() == name then
|
||||
return spec
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
context.getPlayerByName = function(name, multifloor)
|
||||
if not name then return nil end
|
||||
name = name:lower()
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
for i, spec in ipairs(g_map.getSpectators(context.player:getPosition(), multifloor)) do
|
||||
if spec:isPlayer() and spec:getName():lower() == name then
|
||||
return spec
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- tools
|
||||
context.encode = function(data) return json.encode(data) end
|
||||
context.decode = function(text) local status, result = pcall(function() return json.decode(text) end) if status then return result end return {} end
|
||||
end
|
@@ -8,12 +8,24 @@ context.callback = function(callbackType, callback)
|
||||
if callbackType == "onAddThing" or callbackType == "onRemoveThing" then
|
||||
g_game.enableTileThingLuaCallback(true)
|
||||
end
|
||||
|
||||
local desc = "lua"
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
if info then
|
||||
desc = info.short_src .. ":" .. info.currentline
|
||||
end
|
||||
|
||||
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
|
||||
local start = g_clock.realMillis()
|
||||
callback(...)
|
||||
local executionTime = g_clock.realMillis() - start
|
||||
if executionTime > 100 then
|
||||
context.warning("Slow " .. callbackType .. " (" .. executionTime .. "ms): " .. desc)
|
||||
end
|
||||
context._currentExecution = prevExecution
|
||||
end
|
||||
end)
|
||||
|
174
modules/game_bot/functions/icon.lua
Normal file
174
modules/game_bot/functions/icon.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
local context = G.botContext
|
||||
|
||||
local iconsWithoutPosition = 0
|
||||
|
||||
context.addIcon = function(id, options, callback)
|
||||
--[[
|
||||
Available options:
|
||||
item: {id=2160, count=100}
|
||||
outfit: outfit table ({})
|
||||
text: string
|
||||
x: float (0.0 - 1.0)
|
||||
y: float (0.0 - 1.0)
|
||||
width: number
|
||||
height: number
|
||||
hotkey: string
|
||||
switchable: true / false [default: true]
|
||||
movable: true / false [default: true]
|
||||
phantom: true / false [defaule: false]
|
||||
]]--
|
||||
local panel = modules.game_interface.gameMapPanel
|
||||
if type(id) ~= "string" or id:len() < 1 then
|
||||
return context.error("Invalid id for addIcon")
|
||||
end
|
||||
if options.switchable == false and type(callback) ~= 'function' then
|
||||
return context.error("Invalid callback for addIcon")
|
||||
end
|
||||
if type(context.storage._icons) ~= "table" then
|
||||
context.storage._icons = {}
|
||||
end
|
||||
if type(context.storage._icons[id]) ~= "table" then
|
||||
context.storage._icons[id] = {}
|
||||
end
|
||||
local config = context.storage._icons[id]
|
||||
local widget = g_ui.createWidget("BotIcon", panel)
|
||||
widget.botWidget = true
|
||||
|
||||
if type(config.x) ~= 'number' and type(config.y) ~= 'number' then
|
||||
if type(options.x) == 'number' and type(options.y) == 'number' then
|
||||
config.x = math.min(1.0, math.max(0.0, options.x))
|
||||
config.y = math.min(1.0, math.max(0.0, options.y))
|
||||
else
|
||||
config.x = 0.01 + math.floor(iconsWithoutPosition / 5) / 10
|
||||
config.y = 0.05 + (iconsWithoutPosition % 5) / 5
|
||||
iconsWithoutPosition = iconsWithoutPosition + 1
|
||||
end
|
||||
end
|
||||
|
||||
if options.item then
|
||||
if type(options.item) == 'number' then
|
||||
widget.item:setItemId(options.item)
|
||||
else
|
||||
widget.item:setItemId(options.item.id)
|
||||
widget.item:setItemCount(options.item.count or 1)
|
||||
widget.item:setShowCount(false)
|
||||
end
|
||||
end
|
||||
|
||||
if options.outfit then
|
||||
widget.creature:setOutfit(options.outfit)
|
||||
end
|
||||
|
||||
if options.switchable == false then
|
||||
widget.status:hide()
|
||||
widget.status:setOn(true)
|
||||
else
|
||||
widget.status:setOn(config.enabled)
|
||||
end
|
||||
|
||||
if options.text then
|
||||
if options.switchable ~= false then
|
||||
widget.status:hide()
|
||||
if widget.status:isOn() then
|
||||
widget.text:setColor('green')
|
||||
else
|
||||
widget.text:setColor('red')
|
||||
end
|
||||
end
|
||||
widget.text:setText(options.text)
|
||||
end
|
||||
|
||||
widget.setOn = function(val)
|
||||
widget.status:setOn(val)
|
||||
if widget.status:isOn() then
|
||||
widget.text:setColor('green')
|
||||
else
|
||||
widget.text:setColor('red')
|
||||
end
|
||||
config.enabled = widget.status:isOn()
|
||||
end
|
||||
|
||||
widget.onClick = function(widget)
|
||||
if options.switchable ~= false then
|
||||
widget.setOn(not widget.status:isOn())
|
||||
if type(callback) == 'table' then
|
||||
callback.setOn(config.enabled)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
callback(widget, widget.status:isOn())
|
||||
end
|
||||
|
||||
if options.hotkey then
|
||||
widget.hotkey:setText(options.hotkey)
|
||||
context.hotkey(options.hotkey, "", function()
|
||||
widget:onClick()
|
||||
end, nil, options.switchable ~= false)
|
||||
else
|
||||
widget.hotkey:hide()
|
||||
end
|
||||
|
||||
if options.movable ~= false then
|
||||
widget.onDragEnter = function(widget, mousePos)
|
||||
if not g_keyboard.isCtrlPressed() then
|
||||
return false
|
||||
end
|
||||
widget:breakAnchors()
|
||||
widget.movingReference = { x = mousePos.x - widget:getX(), y = mousePos.y - widget:getY() }
|
||||
return true
|
||||
end
|
||||
|
||||
widget.onDragMove = function(widget, mousePos, moved)
|
||||
local parentRect = widget:getParent():getRect()
|
||||
local x = math.min(math.max(parentRect.x, mousePos.x - widget.movingReference.x), parentRect.x + parentRect.width - widget:getWidth())
|
||||
local y = math.min(math.max(parentRect.y, mousePos.y - widget.movingReference.y), parentRect.y + parentRect.height - widget:getHeight())
|
||||
widget:move(x, y)
|
||||
return true
|
||||
end
|
||||
|
||||
widget.onDragLeave = function(widget, pos)
|
||||
local parent = widget:getParent()
|
||||
local parentRect = parent:getRect()
|
||||
local x = widget:getX() - parentRect.x
|
||||
local y = widget:getY() - parentRect.y
|
||||
local width = parentRect.width - widget:getWidth()
|
||||
local height = parentRect.height - widget:getHeight()
|
||||
|
||||
config.x = math.min(1, math.max(0, x / width))
|
||||
config.y = math.min(1, math.max(0, y / height))
|
||||
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
|
||||
widget:addAnchor(AnchorVerticalCenter, 'parent', AnchorVerticalCenter)
|
||||
|
||||
widget:setMarginTop(height * (-0.5 + config.x))
|
||||
widget:setMarginLeft(width * (-0.5 + config.y))
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
widget.onGeometryChange = function(widget, oldRect, newRect)
|
||||
if widget:isDragging() then return end
|
||||
local parent = widget:getParent()
|
||||
local parentRect = parent:getRect()
|
||||
local width = parentRect.width - widget:getWidth()
|
||||
local height = parentRect.height - widget:getHeight()
|
||||
widget:setMarginTop(height * (-0.5 + config.y))
|
||||
widget:setMarginLeft(width * (-0.5 + config.x))
|
||||
end
|
||||
|
||||
if options.phantom ~= true then
|
||||
widget.onMouseRelease = function()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if options.switchable ~= false then
|
||||
if type(callback) == 'table' then
|
||||
callback.setOn(config.enabled)
|
||||
callback.icon = widget
|
||||
else
|
||||
callback(widget, widget.status:isOn())
|
||||
end
|
||||
end
|
||||
return widget
|
||||
end
|
@@ -34,33 +34,89 @@ context.macro = function(timeout, name, hotkey, callback, parent)
|
||||
hotkey = retranslateKeyComboDesc(hotkey)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
if context.storage._macros[name] == nil then
|
||||
context.storage._macros[name] = false
|
||||
table.insert(context._macros, {
|
||||
enabled = false,
|
||||
name = name,
|
||||
timeout = timeout,
|
||||
lastExecution = context.now,
|
||||
hotkey = hotkey,
|
||||
})
|
||||
local macro = context._macros[#context._macros]
|
||||
|
||||
macro.isOn = function()
|
||||
return macro.enabled
|
||||
end
|
||||
macro.isOff = function()
|
||||
return not macro.enabled
|
||||
end
|
||||
macro.toggle = function(widget)
|
||||
if macro.isOn() then
|
||||
macro.setOff()
|
||||
else
|
||||
macro.setOn()
|
||||
end
|
||||
switch = context._addMacroSwitch(name, hotkey, parent)
|
||||
end
|
||||
macro.setOn = function(val)
|
||||
if val == false then
|
||||
return macro.setOff()
|
||||
end
|
||||
macro.enabled = true
|
||||
context.storage._macros[name] = true
|
||||
if macro.switch then
|
||||
macro.switch:setOn(true)
|
||||
end
|
||||
if macro.icon then
|
||||
macro.icon.setOn(true)
|
||||
end
|
||||
end
|
||||
macro.setOff = function(val)
|
||||
if val == false then
|
||||
return macro.setOn()
|
||||
end
|
||||
macro.enabled = false
|
||||
context.storage._macros[name] = false
|
||||
if macro.switch then
|
||||
macro.switch:setOn(false)
|
||||
end
|
||||
if macro.icon then
|
||||
macro.icon.setOn(false)
|
||||
end
|
||||
end
|
||||
|
||||
if name:len() > 0 then
|
||||
-- creature switch
|
||||
local text = name
|
||||
if hotkey:len() > 0 then
|
||||
text = name .. " [" .. hotkey .. "]"
|
||||
end
|
||||
macro.switch = context.addSwitch("macro_" .. (#context._macros + 1), text, macro.toggle, parent)
|
||||
|
||||
-- load state
|
||||
if context.storage._macros[name] == true then
|
||||
macro.setOn()
|
||||
end
|
||||
end
|
||||
|
||||
local desc = "lua"
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
if info then
|
||||
desc = info.short_src .. ":" .. info.currentline
|
||||
end
|
||||
|
||||
table.insert(context._macros, {
|
||||
timeout = timeout,
|
||||
name = name,
|
||||
lastExecution = context.now,
|
||||
hotkey = hotkey,
|
||||
switch = switch
|
||||
})
|
||||
|
||||
local macroData = context._macros[#context._macros]
|
||||
macroData.callback = function()
|
||||
if not macroData.delay or macroData.delay < context.now then
|
||||
context._currentExecution = macroData
|
||||
callback()
|
||||
macro.callback = function(macro)
|
||||
if not macro.delay or macro.delay < context.now then
|
||||
context._currentExecution = macro
|
||||
local start = g_clock.realMillis()
|
||||
callback(macro)
|
||||
local executionTime = g_clock.realMillis() - start
|
||||
if executionTime > 100 then
|
||||
context.warning("Slow macro (" .. executionTime .. "ms): " .. macro.name .. " - " .. desc)
|
||||
end
|
||||
context._currentExecution = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return macroData
|
||||
return macro
|
||||
end
|
||||
|
||||
-- hotkey(keys, callback)
|
||||
@@ -94,11 +150,22 @@ context.hotkey = function(keys, name, callback, parent, single)
|
||||
single = single
|
||||
}
|
||||
|
||||
local desc = "lua"
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
if info then
|
||||
desc = info.short_src .. ":" .. info.currentline
|
||||
end
|
||||
|
||||
local hotkeyData = context._hotkeys[keys]
|
||||
hotkeyData.callback = function()
|
||||
if not hotkeyData.delay or hotkeyData.delay < context.now then
|
||||
context._currentExecution = hotkeyData
|
||||
local start = g_clock.realMillis()
|
||||
callback()
|
||||
local executionTime = g_clock.realMillis() - start
|
||||
if executionTime > 100 then
|
||||
context.warning("Slow hotkey (" .. executionTime .. "ms): " .. hotkeyData.name .. " - " .. desc)
|
||||
end
|
||||
context._currentExecution = nil
|
||||
return true
|
||||
end
|
||||
|
@@ -132,7 +132,6 @@ context.findPath = function(startPos, destPos, maxDist, params)
|
||||
local destPosStr = destPos.x .. "," .. destPos.y .. "," .. destPos.z
|
||||
params["destination"] = destPosStr
|
||||
local paths = context.findAllPaths(startPos, maxDist, params)
|
||||
|
||||
local marginMin = params.marginMin or params.minMargin
|
||||
local marginMax = params.marginMax or params.maxMargin
|
||||
if type(marginMin) == 'number' and type(marginMax) == 'number' then
|
||||
@@ -143,6 +142,7 @@ context.findPath = function(startPos, destPos, maxDist, params)
|
||||
if math.abs(x) >= marginMin or math.abs(y) >= marginMin then
|
||||
local dest = (destPos.x + x) .. "," .. (destPos.y + y) .. "," .. destPos.z
|
||||
local node = paths[dest]
|
||||
print(node)
|
||||
if node and (not bestCandidate or bestCandidate[1] > node[1]) then
|
||||
bestCandidate = node
|
||||
bestCandidatePos = dest
|
||||
@@ -195,3 +195,7 @@ context.autoWalk = function(destination, maxDist, params)
|
||||
return true
|
||||
end
|
||||
|
||||
context.getTileUnderCursor = function()
|
||||
if not modules.game_interface.gameMapPanel.mousePos then return end
|
||||
return modules.game_interface.gameMapPanel:getTile(modules.game_interface.gameMapPanel.mousePos)
|
||||
end
|
@@ -3,6 +3,7 @@ local context = G.botContext
|
||||
context.BotServer = {}
|
||||
context.BotServer.url = "ws://bot.otclient.ovh:8000/"
|
||||
context.BotServer.timeout = 3
|
||||
context.BotServer.ping = 0
|
||||
context.BotServer._callbacks = {}
|
||||
context.BotServer._lastMessageId = 0
|
||||
context.BotServer._wasConnected = true -- show first warning
|
||||
@@ -24,6 +25,7 @@ context.BotServer.init = function(name, channel)
|
||||
end
|
||||
context.BotServer._wasConnected = true
|
||||
if message["type"] == "ping" then
|
||||
context.BotServer.ping = message["ping"]
|
||||
return context.BotServer._websocket.send({type="ping"})
|
||||
end
|
||||
if message["type"] == "message" then
|
||||
|
@@ -59,7 +59,7 @@ Panel
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
vertical-scrollbar: scrollBar
|
||||
margin-right: 10
|
||||
margin-right: 5
|
||||
margin-top: 2
|
||||
height: 70
|
||||
layout:
|
||||
@@ -67,7 +67,7 @@ Panel
|
||||
cell-size: 34 34
|
||||
flow: true
|
||||
|
||||
VerticalScrollBar
|
||||
BotSmallScrollBar
|
||||
id: scrollBar
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
|
@@ -38,6 +38,67 @@ BotSeparator < HorizontalSeparator
|
||||
margin-top: 5
|
||||
margin-bottom: 3
|
||||
|
||||
BotSmallScrollBar < UIScrollBar
|
||||
orientation: vertical
|
||||
margin-bottom: 1
|
||||
step: 20
|
||||
width: 8
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 39 0 13 65
|
||||
image-border: 1
|
||||
pixels-scroll: true
|
||||
|
||||
UIButton
|
||||
id: decrementButton
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 0 13 13
|
||||
image-color: #ffffffff
|
||||
size: 8 8
|
||||
$hover:
|
||||
image-clip: 13 0 13 13
|
||||
$pressed:
|
||||
image-clip: 26 0 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
UIButton
|
||||
id: incrementButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
size: 8 8
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 13 13 13
|
||||
image-color: #ffffffff
|
||||
$hover:
|
||||
image-clip: 13 13 13 13
|
||||
$pressed:
|
||||
image-clip: 26 13 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
UIButton
|
||||
id: sliderButton
|
||||
anchors.centerIn: parent
|
||||
size: 8 11
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 26 13 13
|
||||
image-border: 2
|
||||
image-color: #ffffffff
|
||||
$hover:
|
||||
image-clip: 13 26 13 13
|
||||
$pressed:
|
||||
image-clip: 26 26 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
Label
|
||||
id: valueLabel
|
||||
anchors.fill: parent
|
||||
color: white
|
||||
text-align: center
|
||||
|
||||
BotPanel < Panel
|
||||
ScrollablePanel
|
||||
id: content
|
||||
@@ -49,70 +110,11 @@ BotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
UIScrollBar
|
||||
BotSmallScrollBar
|
||||
id: botPanelScroll
|
||||
orientation: vertical
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
margin-bottom: 1
|
||||
step: 20
|
||||
width: 8
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 39 0 13 65
|
||||
image-border: 1
|
||||
pixels-scroll: true
|
||||
|
||||
UIButton
|
||||
id: decrementButton
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 0 13 13
|
||||
image-color: #ffffffff
|
||||
size: 8 8
|
||||
$hover:
|
||||
image-clip: 13 0 13 13
|
||||
$pressed:
|
||||
image-clip: 26 0 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
UIButton
|
||||
id: incrementButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
size: 8 8
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 13 13 13
|
||||
image-color: #ffffffff
|
||||
$hover:
|
||||
image-clip: 13 13 13 13
|
||||
$pressed:
|
||||
image-clip: 26 13 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
UIButton
|
||||
id: sliderButton
|
||||
anchors.centerIn: parent
|
||||
size: 8 11
|
||||
image-source: /images/ui/scrollbar
|
||||
image-clip: 0 26 13 13
|
||||
image-border: 2
|
||||
image-color: #ffffffff
|
||||
$hover:
|
||||
image-clip: 13 26 13 13
|
||||
$pressed:
|
||||
image-clip: 26 26 13 13
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
|
||||
Label
|
||||
id: valueLabel
|
||||
anchors.fill: parent
|
||||
color: white
|
||||
text-align: center
|
||||
|
||||
CaveBotLabel < Label
|
||||
background-color: alpha
|
||||
|
60
modules/game_bot/ui/icons.otui
Normal file
60
modules/game_bot/ui/icons.otui
Normal file
@@ -0,0 +1,60 @@
|
||||
BotIcon < UIWidget
|
||||
size: 50 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
focusable: false
|
||||
phantom: false
|
||||
draggable: true
|
||||
|
||||
UIItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 6
|
||||
virtual: true
|
||||
phantom: true
|
||||
size: 32 32
|
||||
|
||||
UICreature
|
||||
id: creature
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 0
|
||||
size: 48 48
|
||||
phantom: true
|
||||
|
||||
UIWidget
|
||||
id: status
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
size: 18 10
|
||||
color: black
|
||||
font: terminus-10px
|
||||
phantom: true
|
||||
|
||||
$on:
|
||||
text: ON
|
||||
background: green
|
||||
|
||||
$!on:
|
||||
text: OFF
|
||||
background: red
|
||||
|
||||
UIWidget
|
||||
id: hotkey
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
size: 18 10
|
||||
color: white
|
||||
phantom: true
|
||||
text-align: right
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-wrap: true
|
||||
text-auto-resize: true
|
||||
phantom: true
|
Reference in New Issue
Block a user