Updated to OTCv8 3.1 rev 132

This commit is contained in:
OTCv8 2022-02-17 11:22:38 +00:00
parent 80177bd151
commit db1d638018
135 changed files with 5381 additions and 2684 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

BIN
data/minimap.otmm Normal file

Binary file not shown.

View File

@ -12,6 +12,9 @@ ProgressBar < UIProgressBar
margin-bottom: 0
height: 0
ThickProgressBar < ProgressBar
image-source: /images/ui/progressbar_thick
LifeProgressBar < UIProgressBar
height: 16
background-color: green

View File

@ -0,0 +1,127 @@
OptionPanel
Label
text: Client user features profile
ComboBox
id: profile
margin-top: 3
@onOptionChange: modules.client_options.setOption(self:getId(), self.currentIndex)
@onSetup: |
self:addOption("1")
self:addOption("2")
self:addOption("3")
self:addOption("4")
self:addOption("5")
self:addOption("6")
self:addOption("7")
self:addOption("8")
self:addOption("9")
self:addOption("10")
Label
OptionCheckBox
id: topBar
!text: tr('Show customizable top status bar')
OptionCheckBox
id: topHealtManaBar
!text: tr('Show player top health and mana bar')
OptionCheckBox
id: showHealthManaCircle
!text: tr('Show health and mana circle')
$mobile:
visible: false
Label
margin-top: 5
text: Show Bottom Action Bars:
Panel
margin-top: 2
height: 16
layout:
type: horizontalBox
OptionCheckBox
id: actionbarBottom1
!text: tr('Bar 1')
width: 60
OptionCheckBox
id: actionbarBottom2
!text: tr('Bar 2')
width: 60
OptionCheckBox
id: actionbarBottom3
!text: tr('Bar 3')
width: 60
Label
text: Show Left Action Bars:
$mobile:
visible: false
Panel
margin-top: 2
height: 16
$mobile:
visible: false
layout:
type: horizontalBox
OptionCheckBox
id: actionbarLeft1
!text: tr('Bar 1')
width: 60
OptionCheckBox
id: actionbarLeft2
!text: tr('Bar 2')
width: 60
OptionCheckBox
id: actionbarLeft3
!text: tr('Bar 3')
width: 60
Label
text: Show Right Action Bars:
$mobile:
visible: false
Panel
margin-top: 2
height: 16
layout:
type: horizontalBox
$mobile:
visible: false
OptionCheckBox
id: actionbarRight1
!text: tr('Bar 1')
width: 60
OptionCheckBox
id: actionbarRight2
!text: tr('Bar 2')
width: 60
OptionCheckBox
id: actionbarRight3
!text: tr('Bar 3')
width: 60
Label
OptionCheckBox
id: actionbarLock
!text: tr('Disable action bar hotkeys when chat mode is on')
$mobile:
visible: false

View File

@ -37,14 +37,6 @@ OptionPanel
$mobile:
visible: false
OptionCheckBox
id: actionBar1
!text: tr("Show first action bar")
OptionCheckBox
id: actionBar2
!text: tr("Show second action bar")
OptionCheckBox
id: showPing
!text: tr('Show connection ping')
@ -74,16 +66,6 @@ OptionPanel
$mobile:
visible: false
OptionCheckBox
id: topHealtManaBar
!text: tr('Show player top health and mana bar')
OptionCheckBox
id: showHealthManaCircle
!text: tr('Show health and mana circle')
$mobile:
visible: false
OptionCheckBox
id: highlightThingsUnderCursor
!text: tr('Highlight things under cursor')

View File

@ -50,8 +50,23 @@ local defaultOptions = {
walkTeleportDelay = 200,
walkCtrlTurnDelay = 150,
actionBar1 = true,
actionBar2 = false
topBar = true,
actionbarBottom1 = true,
actionbarBottom2 = false,
actionbarBottom3 = false,
actionbarLeft1 = false,
actionbarLeft2 = false,
actionbarLeft3 = false,
actionbarRight1 = false,
actionbarRight2 = false,
actionbarRight3 = false,
actionbarLock = true,
profile = 1
}
local optionsWindow
@ -63,7 +78,8 @@ local generalPanel
local interfacePanel
local consolePanel
local graphicsPanel
local soundPanel
local audioPanel
local customPanel
local extrasPanel
local audioButton
@ -101,6 +117,7 @@ function init()
audioPanel = g_ui.loadUI('audio')
optionsTabBar:addTab(tr('Audio'), audioPanel, '/images/optionstab/audio')
extrasPanel = g_ui.createWidget('OptionPanel')
for _, v in ipairs(g_extras.getAll()) do
local extrasButton = g_ui.createWidget('OptionCheckBox')
@ -112,6 +129,9 @@ function init()
optionsTabBar:addTab(tr('Extras'), extrasPanel, '/images/optionstab/extras')
end
customPanel = g_ui.loadUI('custom')
optionsTabBar:addTab(tr('Custom'), customPanel, '/images/optionstab/features')
optionsButton = modules.client_topmenu.addLeftButton('optionsButton', tr('Options'), '/images/topbuttons/options', toggle)
audioButton = modules.client_topmenu.addLeftButton('audioButton', tr('Audio'), '/images/topbuttons/audio', function() toggleOption('enableAudio') end)
if g_app.isMobile() then
@ -357,11 +377,19 @@ function setOption(key, value, force)
g_settings.set(key, value)
options[key] = value
if key == "profile" then
modules.client_profiles.onProfileChange()
end
if key == 'classicView' or key == 'rightPanels' or key == 'leftPanels' or key == 'cacheMap' then
modules.game_interface.refreshViewMode()
elseif key == 'actionBar1' or key == 'actionBar2' then
elseif key:find("actionbar") then
modules.game_actionbar.show()
end
if key == 'topBar' then
modules.game_topbar.show()
end
end
function getOption(key)

View File

@ -0,0 +1,160 @@
local settings = {}
ChangedProfile = false
function init()
connect(g_game, {
onGameStart = online,
onGameEnd = offline
})
end
function terminate()
disconnect(g_game, {
onGameStart = online,
onGameEnd = offline
})
end
-- loads settings on character login
function online()
ChangedProfile = false
-- startup arguments has higher priority than settings
local index = getProfileFromStartupArgument()
if index then
setProfileOption(index)
end
load()
if not index then
setProfileOption(getProfileFromSettings() or 1)
end
-- create main settings dir
if not g_resources.directoryExists("/settings/") then
g_resources.makeDir("/settings/")
end
-- create profiles dirs
for i=1,10 do
local path = "/settings/profile_"..i
if not g_resources.directoryExists(path) then
g_resources.makeDir(path)
end
end
end
function setProfileOption(index)
local currentProfile = g_settings.getNumber('profile')
currentProfile = tostring(currentProfile)
index = tostring(index)
if currentProfile ~= index then
ChangedProfile = true
return modules.client_options.setOption('profile', index)
end
end
-- load profile number from settings
function getProfileFromSettings()
-- settings should save per character, return if not online
if not g_game.isOnline() then return end
local index = g_game.getCharacterName()
local savedData = settings[index]
return savedData
end
-- option to launch client with hardcoded profile
function getProfileFromStartupArgument()
local startupOptions = string.split(g_app.getStartupOptions(), " ")
if #startupOptions < 2 then
return false
end
for index, option in ipairs(startupOptions) do
if option == "--profile" then
local profileIndex = startupOptions[index + 1]
if profileIndex == nil then
return g_logger.info("Startup arguments incomplete: missing profile index.")
end
g_logger.info("Startup options: Forced profile: "..profileIndex)
-- set value in options
return profileIndex
end
end
return false
end
-- returns string path ie. "/settings/1/actionbar.json"
function getSettingsFilePath(fileNameWithFormat)
local currentProfile = g_settings.getNumber('profile')
return "/settings/profile_"..currentProfile.."/"..fileNameWithFormat
end
function offline()
onProfileChange(true)
end
-- profile change callback (called in options), saves settings & reloads given module configs
function onProfileChange(offline)
if not offline then
if not g_game.isOnline() then return end
-- had to apply some delay
scheduleEvent(collectiveReload, 100)
end
local currentProfile = g_settings.getNumber('profile')
local index = g_game.getCharacterName()
if index then
settings[index] = currentProfile
save()
end
end
-- collection of refresh functions from different modules
function collectiveReload()
modules.game_topbar.refresh(true)
modules.game_actionbar.refresh(true)
modules.game_bot.refresh()
end
-- json handlers
function load()
local file = "/settings/profiles.json"
if g_resources.fileExists(file) then
local status, result = pcall(function()
return json.decode(g_resources.readFileContents(file))
end)
if not status then
return onError(
"Error while reading profiles file. To fix this problem you can delete storage.json. Details: " ..
result)
end
settings = result
end
end
function save()
local file = "/settings/profiles.json"
local status, result = pcall(function() return json.encode(settings, 2) end)
if not status then
return onError(
"Error while saving profile settings. Data won't be saved. Details: " ..
result)
end
if result:len() > 100 * 1024 * 1024 then
return onError(
"Something went wrong, file is above 100MB, won't be saved")
end
g_resources.writeFileContents(file, result)
end

View File

@ -0,0 +1,11 @@
Module
name: client_profiles
description: Provides option to save client customizations into separate profiles
author: Vithrax
discord: Vithrax#5814
autoload: true
reloadable: false
scripts: [ profiles ]
sandboxed: true
@onLoad: init()
@onUnload: terminate()

View File

@ -1,7 +1,12 @@
actionPanel1 = nil
actionPanel2 = nil
---@diagnostic disable: undefined-global
bottomActionPanel1 = nil
bottomActionPanel2 = nil
bottomActionPanel3 = nil
leftActionPanel1 = nil
leftActionPanel2 = nil
leftActionPanel3 = nil
local actionConfig
local settings = {}
local hotkeyAssignWindow
local actionButtonsInPanel = 50
@ -24,13 +29,33 @@ ActionColors = {
}
function init()
local bottomPanel = modules.game_interface.getActionPanel()
actionPanel1 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(actionPanel1, 1)
actionPanel2 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(actionPanel2, 1)
local bottomPanel = modules.game_interface.getBottomActionPanel()
local leftPanel = modules.game_interface.getLeftActionPanel()
local rightPanel = modules.game_interface.getRightActionPanel()
actionConfig = g_configs.create("/actionbar.otml")
-- bottom
bottomActionPanel1 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(bottomActionPanel1, 1)
bottomActionPanel2 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(bottomActionPanel2, 1)
bottomActionPanel3 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(bottomActionPanel3, 1)
-- left
leftActionPanel1 = g_ui.loadUI('sideactionbar', leftPanel)
leftPanel:moveChildToIndex(leftActionPanel1, 1)
leftActionPanel2 = g_ui.loadUI('sideactionbar', leftPanel)
leftPanel:moveChildToIndex(leftActionPanel2, 1)
leftActionPanel3 = g_ui.loadUI('sideactionbar', leftPanel)
leftPanel:moveChildToIndex(leftActionPanel3, 1)
-- right
rightActionPanel1 = g_ui.loadUI('sideactionbar', rightPanel)
rightPanel:moveChildToIndex(rightActionPanel1, 1)
rightActionPanel2 = g_ui.loadUI('sideactionbar', rightPanel)
rightPanel:moveChildToIndex(rightActionPanel2, 1)
rightActionPanel3 = g_ui.loadUI('sideactionbar', rightPanel)
rightPanel:moveChildToIndex(rightActionPanel3, 1)
connect(g_game, {
onGameStart = online,
@ -53,42 +78,105 @@ function terminate()
})
-- remove hotkeys, also saves config
if actionPanel1.tabBar:getChildCount() > 0 and actionPanel2.tabBar:getChildCount() > 0 then
local panels = {
bottomActionPanel1,
bottomActionPanel2,
bottomActionPanel3,
leftActionPanel1,
leftActionPanel2,
leftActionPanel3,
rightActionPanel1,
rightActionPanel2,
rightActionPanel3,
}
for i, panel in ipairs(panels) do
if panel.tabBar:getChildCount() > 0 then
offline()
break
end
end
actionPanel1:destroy()
actionPanel2:destroy()
bottomActionPanel1:destroy()
bottomActionPanel2:destroy()
bottomActionPanel3:destroy()
leftActionPanel1:destroy()
leftActionPanel2:destroy()
leftActionPanel3:destroy()
rightActionPanel1:destroy()
rightActionPanel2:destroy()
rightActionPanel3:destroy()
end
function show()
if not g_game.isOnline() then return end
actionPanel1:setOn(g_settings.getBoolean("actionBar1", false))
actionPanel2:setOn(g_settings.getBoolean("actionBar2", false))
bottomActionPanel1:setOn(g_settings.getBoolean("actionbarBottom1", false))
bottomActionPanel2:setOn(g_settings.getBoolean("actionbarBottom2", false))
bottomActionPanel3:setOn(g_settings.getBoolean("actionbarBottom3", false))
leftActionPanel1:setOn(g_settings.getBoolean("actionbarLeft1", false))
leftActionPanel2:setOn(g_settings.getBoolean("actionbarLeft2", false))
leftActionPanel3:setOn(g_settings.getBoolean("actionbarLeft3", false))
rightActionPanel1:setOn(g_settings.getBoolean("actionbarRight1", false))
rightActionPanel2:setOn(g_settings.getBoolean("actionbarRight2", false))
rightActionPanel3:setOn(g_settings.getBoolean("actionbarRight3", false))
end
function hide()
actionPanel1:setOn(false)
actionPanel2:setOn(false)
bottomActionPanel1:setOn(false)
bottomActionPanel2:setOn(false)
bottomActionPanel3:setOn(false)
leftActionPanel1:setOn(false)
leftActionPanel2:setOn(false)
leftActionPanel3:setOn(false)
rightActionPanel1:setOn(false)
rightActionPanel2:setOn(false)
rightActionPanel3:setOn(false)
end
function switchMode(newMode)
if newMode then
actionPanel1:setImageColor('#ffffff88')
actionPanel2:setImageColor('#ffffff88')
bottomActionPanel1:setImageColor('#ffffff88')
bottomActionPanel2:setImageColor('#ffffff88')
bottomActionPanel3:setImageColor('#ffffff88')
leftActionPanel1:setImageColor('#ffffff88')
leftActionPanel2:setImageColor('#ffffff88')
leftActionPanel3:setImageColor('#ffffff88')
rightActionPanel1:setImageColor('#ffffff88')
rightActionPanel2:setImageColor('#ffffff88')
rightActionPanel3:setImageColor('#ffffff88')
else
actionPanel1:setImageColor('white')
actionPanel2:setImageColor('white')
bottomActionPanel1:setImageColor('white')
bottomActionPanel2:setImageColor('white')
bottomActionPanel3:setImageColor('white')
leftActionPanel1:setImageColor('white')
leftActionPanel2:setImageColor('white')
leftActionPanel3:setImageColor('white')
rightActionPanel1:setImageColor('white')
rightActionPanel2:setImageColor('white')
rightActionPanel3:setImageColor('white')
end
end
function online()
setupActionPanel(1, actionPanel1)
setupActionPanel(2, actionPanel2)
load()
setupActionPanel(1, bottomActionPanel1, true)
setupActionPanel(2, bottomActionPanel2, true)
setupActionPanel(3, bottomActionPanel3, true)
setupActionPanel(4, leftActionPanel1, false)
setupActionPanel(5, leftActionPanel2, false)
setupActionPanel(6, leftActionPanel3, false)
setupActionPanel(7, rightActionPanel1, false)
setupActionPanel(8, rightActionPanel2, false)
setupActionPanel(9, rightActionPanel3, false)
show()
end
function offline()
function refresh(reloaded)
offline(reloaded)
online()
end
function offline(reloaded)
hide()
if hotkeyAssignWindow then
hotkeyAssignWindow:destroy()
@ -96,37 +184,35 @@ function offline()
end
local gameRootPanel = modules.game_interface.getRootPanel()
for index, panel in ipairs({actionPanel1, actionPanel2}) do
local config = {}
for index, panel in ipairs({bottomActionPanel1, bottomActionPanel2, bottomActionPanel3,
leftActionPanel1, leftActionPanel2, leftActionPanel3,
rightActionPanel1, rightActionPanel2, rightActionPanel3}) do
settings[tostring(index)] = {}
for i, child in ipairs(panel.tabBar:getChildren()) do
if child.config then
table.insert(config, child.config)
if child.config and child.config.item then
settings[tostring(index)][tostring(i)] = child.config
if type(child.config.hotkey) == 'string' and child.config.hotkey:len() > 0 then
g_keyboard.unbindKeyPress(child.config.hotkey, child.callback, gameRootPanel)
end
else
table.insert(config, {})
end
if child.cooldownEvent then
removeEvent(child.cooldownEvent)
end
end
actionConfig:setNode('actions_' .. index, config)
panel.tabBar:destroyChildren()
end
actionConfig:save()
if not reloaded then
save()
end
end
function setupActionPanel(index, panel)
local rawConfig = actionConfig:getNode('actions_' .. index) or {}
local config = {}
for i, buttonConfig in pairs(rawConfig) do -- sorting, because key in rawConfig is string
config[tonumber(i)] = buttonConfig
end
function setupActionPanel(index, panel, bottom)
local config = settings[tostring(index)] or {}
for i=1,actionButtonsInPanel do
local action = g_ui.createWidget('ActionButton', panel.tabBar)
action.config = config[i] or {}
local type = bottom and 'ActionButton' or 'SideActionButton'
local action = g_ui.createWidget(type, panel.tabBar)
action.config = config[tostring(i)] or {}
setupAction(action)
end
@ -143,7 +229,18 @@ function setupAction(action)
action.item:setShowCount(false)
action.onMouseRelease = actionOnMouseRelease
action.onTouchRelease = actionOnMouseRelease
action.callback = function(k, c, ticks) executeAction(action, ticks) end
action.callback = function(k, c, ticks)
local lockKeyboard = g_settings.getBoolean('actionbarLock', false)
local chatMode = not modules.game_walking.wsadWalking
if not lockKeyboard or not chatMode then
print('lock', lockKeyboard)
print('chatMode', chatMode)
executeAction(action, ticks)
end
end
action.item.onItemChange = nil -- disable callbacks for setup
if config then
@ -327,7 +424,9 @@ function actionOnItemChange(widget)
end
function onSpellCooldown(iconId, duration)
for index, panel in ipairs({actionPanel1, actionPanel2}) do
for index, panel in ipairs({bottomActionPanel1, bottomActionPanel2, bottomActionPanel3,
leftActionPanel1, leftActionPanel2, leftActionPanel3,
rightActionPanel1, rightActionPanel2, rightActionPanel3}) do
for i, child in ipairs(panel.tabBar:getChildren()) do
if child.spell and child.spell.id == iconId then
startCooldown(child, duration)
@ -337,7 +436,9 @@ function onSpellCooldown(iconId, duration)
end
function onSpellGroupCooldown(groupId, duration)
for index, panel in ipairs({actionPanel1, actionPanel2}) do
for index, panel in ipairs({bottomActionPanel1, bottomActionPanel2, bottomActionPanel3,
leftActionPanel1, leftActionPanel2, leftActionPanel3,
rightActionPanel1, rightActionPanel2, rightActionPanel3}) do
for i, child in ipairs(panel.tabBar:getChildren()) do
if child.spell and child.spell.group then
for group, dur in pairs(child.spell.group) do
@ -484,3 +585,39 @@ function executeAction(action, ticks)
end
end
end
function save()
local settingsFile = modules.client_profiles.getSettingsFilePath("actionbar.json")
local status, result = pcall(function() return json.encode(settings, 2) end)
if not status then
return onError(
"Error while saving top bar settings. Data won't be saved. Details: " ..
result)
end
if result:len() > 100 * 1024 * 1024 then
return onError(
"Something went wrong, file is above 100MB, won't be saved")
end
g_resources.writeFileContents(settingsFile, result)
end
function load()
local settingsFile = modules.client_profiles.getSettingsFilePath("actionbar.json")
if g_resources.fileExists(settingsFile) then
local status, result = pcall(function()
return json.decode(g_resources.readFileContents(settingsFile))
end)
if not status then
return onError(
"Error while reading top bar settings file. To fix this problem you can delete storage.json. Details: " ..
result)
end
settings = result
else
settings = {}
end
end

View File

@ -5,6 +5,7 @@ ActionButton < Panel
width: 40
padding: 1 1 1 1
margin-left: 1
draggable: true
$first:
anchors.left: parent.left
@ -101,7 +102,6 @@ Panel
margin-top: 1
margin-bottom: 2
ActionAssignWindow < MainWindow
id: assignWindow
!text: tr('Button Assign')

View File

@ -0,0 +1,149 @@
SideActionButton < Panel
font: cipsoftFont
anchors.left: parent.left
anchors.right: parent.right
height: 40
padding: 1 1 1 1
margin-top: 1
draggable: true
$first:
anchors.top: parent.top
margin-top: -3
$!first:
anchors.top: prev.bottom
Item
id: item
anchors.fill: parent
&selectable: true
&editable: false
virtual: true
border-width: 1
border-color: #00000000
$!on:
image-source: /images/game/actionbarslot
Label
id: text
anchors.fill: parent
text-auto-resize: true
text-wrap: true
phantom: true
text-align: center
font: verdana-9px
Label
id: hotkeyLabel
anchors.top: parent.top
anchors.right: parent.right
margin: 2 3 3 3
text-auto-resize: true
text-wrap: false
phantom: true
font: cipsoftFont
color: white
background: #292A2A
UIProgressRect
id: cooldown
background: #585858AA
percent: 100
focusable: false
phantom: true
anchors.fill: parent
margin: 1 1 1 1
font: verdana-11px-rounded
color: white
Panel
id: actionBar
focusable: false
image-source: /images/ui/panel_side
image-border: 4
margin-top: -2
$on:
width: 40
visible: true
$!on:
width: 0
visible: false
TabButton
id: prevButton
icon: /images/game/console/uparrow
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
margin-top: -1
margin-left: 1
margin-right: 1
Panel
id: tabBar
anchors.top: prev.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: next.top
margin-top: 3
clipping: true
TabButton
id: nextButton
icon: /images/game/console/downarrow
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
margin-right: 1
margin-left: 1
margin-bottom: 2
ActionAssignWindow < MainWindow
id: assignWindow
!text: tr('Button Assign')
size: 360 150
@onEscape: self:destroy()
Label
!text: tr('Please, press the key you wish to use for action')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
text-auto-resize: true
text-align: left
Label
id: comboPreview
!text: tr('Current action hotkey: %s', 'none')
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 10
text-auto-resize: true
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin-bottom: 10
Button
id: addButton
!text: tr('Add')
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
Button
id: cancelButton
!text: tr('Cancel')
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: self:getParent():destroy()

View File

@ -190,7 +190,13 @@ function refresh()
-- storage
botStorage = {}
botStorageFile = "/bot/" .. configName .. "/storage.json"
local path = "/bot/" .. configName .. "/storage/"
if not g_resources.directoryExists(path) then
g_resources.makeDir(path)
end
botStorageFile = path.."profile_" .. g_settings.getNumber('profile') .. ".json"
if g_resources.fileExists(botStorageFile) then
local status, result = pcall(function()
return json.decode(g_resources.readFileContents(botStorageFile))
@ -255,7 +261,9 @@ end
function online()
botButton:show()
if not modules.client_profiles.ChangedProfile then
scheduleEvent(refresh, 20)
end
end
function offline()

View File

@ -1,65 +0,0 @@
setDefaultTab("Cave")
local panelName = "specialDeposit"
local depositerPanel
UI.Button("Depositer Settings", function()
depositerPanel:show()
depositerPanel:raise()
depositerPanel:focus()
end)
if not storage[panelName] then
storage[panelName] = {
items = {}
}
end
local config = storage[panelName]
local rootWidget = g_ui.getRootWidget()
if rootWidget then
depositerPanel = UI.createWindow('DepositerPanel', rootWidget)
depositerPanel:hide()
-- basic one
depositerPanel.CloseButton.onClick = function()
depositerPanel:hide()
end
if config.items and #config.items > 0 then
for _, value in ipairs(config.items) do
local label = g_ui.createWidget("ItemLabel", depositerPanel.DepositerList)
label.remove.onClick = function(widget)
table.remove(config.items, table.find(value))
label:destroy()
end
label:setText("Stash (".. value.id .. ") to depot: (" .. value.index .. ")")
end
end
depositerPanel.Add.onClick = function(widget)
local itemId = depositerPanel.ID:getItemId()
local index = tonumber(depositerPanel.Index:getText())
if index and itemId > 100 and not config.items[itemId] then
local value = {id=itemId,index=index}
table.insert(config.items, value)
local label = g_ui.createWidget("ItemLabel", depositerPanel.DepositerList)
label.remove.onClick = function(widget)
table.remove(config.items, table.find(value))
label:destroy()
end
label:setText("Stash (".. itemId .. ") to depot: (" .. index..")")
depositerPanel.ID:setItemId(0)
depositerPanel.Index:setText(0)
end
end
end
function getStashingIndex(id)
for _, v in pairs(config.items) do
if v.id == id then
return v.index - 1
end
end
end

View File

@ -1,86 +0,0 @@
ItemLabel < Label
background-color: alpha
text-offset: 2 0
focusable: true
height: 16
$focus:
background-color: #00000055
Button
id: remove
!text: tr('x')
anchors.right: parent.right
margin-right: 15
width: 15
height: 15
DepositerPanel < MainWindow
size: 250 450
!text: tr('Depositer Panel')
@onEscape: self:hide()
TextList
id: DepositerList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
margin-top: 15
margin-bottom: 5
margin-right: 3
padding: 1
height: 300
vertical-scrollbar: DepositerScrollBar
VerticalScrollBar
id: DepositerScrollBar
anchors.top: DepositerList.top
anchors.bottom: DepositerList.bottom
anchors.right: DepositerList.right
step: 14
pixels-scroll: true
BotItem
id: ID
anchors.top: DepositerList.bottom
margin-top: 3
anchors.left: DepositerList.left
SpinBox
id: Index
anchors.top: DepositerList.bottom
margin-top: 3
anchors.left: prev.right
margin-left: 3
anchors.bottom: prev.bottom
width: 50
minimum: 3
maximum: 17
step: 1
text-align: center
Button
id: Add
anchors.top: DepositerList.bottom
margin-top: 3
anchors.left: prev.right
margin-left: 3
anchors.right: DepositerList.right
anchors.bottom: prev.bottom
!text: tr('Add Item')
HorizontalSeparator
anchors.bottom: CloseButton.top
margin-bottom: 5
anchors.left: parent.left
anchors.right: parent.right
Button
id: CloseButton
anchors.right: parent.right
anchors.bottom: parent.bottom
margin-right: 5
margin-bottom: 5
!text: tr('Close')
font: cipsoftFont
size: 41 25

View File

@ -1,477 +0,0 @@
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 = "-"
if not storage.bestHit or type(storage.bestHit) ~= "number" then
storage.bestHit = 0
end
if not storage.bestHeal or type(storage.bestHeal) ~= "number" then
storage.bestHeal = 0
end
local resetSessionData = function()
launchTime = now
startExp = exp()
dmgTable = {}
healTable = {}
expTable = {}
totalDmg = 0
totalHeal = 0
dmgDistribution = {}
first = "-"
second = "-"
third = "-"
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 sessionTime = function()
uptime = math.floor((now - launchTime)/1000)
return niceTimeFormat(uptime)
end
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) > storage.bestHit then
storage.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) > storage.bestHeal then
storage.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
local ui = setupUI([[
Panel
height: 320
padding: 5
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: 5
anchors.left: parent.left
anchors.right: parent.right
text: Reset Session
Label
id: SessionLabel
anchors.top: prev.bottom
margin-top: 3
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: 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: 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: -
]])
ui:setId("analyzers")
local function toggleHeight()
local h = ui:getHeight()
if h == 320 then
ui:setHeight(28)
else
ui:setHeight(320)
end
end
toggleHeight()
ui.reset.onClick = function(widget)
resetSessionData()
end
ui.toggle.onClick = function(widget)
toggleHeight()
end
macro(500, function()
-- refresh part
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(storage.bestHit))
ui.nine:setText(format_thousand(totalHeal))
ui.ten:setText(format_thousand(valueInSeconds(healTable)))
ui.eleven:setText(format_thousand(storage.bestHeal))
ui.dOne:setText(first)
ui.dTwo:setText(second)
ui.dThree:setText(third)
end)

View File

@ -1,78 +0,0 @@
setDefaultTab("Tools")
UI.Label("Items Management")
UI.Separator()
UI.Label("Trash items:")
if type(storage.trashItems) ~= "table" or not storage.trashItems then
storage.trashItems = {283, 284, 285}
end
local dropContainer = UI.Container(function(widget, items)
storage.trashItems = items
end, true)
dropContainer:setHeight(35)
dropContainer:setItems(storage.trashItems)
macro(200, "Drop Items", function()
if not storage.trashItems[1] then return end
for _, container in pairs(g_game.getContainers()) do
for __, item in ipairs(container:getItems()) do
for i, trashItem in ipairs(storage.trashItems) do
if item:getId() == trashItem.id then
return g_game.move(item, pos(), item:getCount())
end
end
end
end
end)
UI.Label("Items to use:")
if type(storage.useItems) ~= "table" or not storage.useItems then
storage.useItems = {21203, 14758}
end
local useContainer = UI.Container(function(widget, items)
storage.useItems = items
end, true)
useContainer:setHeight(35)
useContainer:setItems(storage.useItems)
macro(200, "Use Items", function()
if not storage.useItems[1] then return end
for _, container in pairs(g_game.getContainers()) do
for __, item in ipairs(container:getItems()) do
for i, useItem in ipairs(storage.useItems) do
if item:getId() == useItem.id then
return use(item)
end
end
end
end
end)
UI.Label("Items to drop below 150 cap:")
if type(storage.lowCapDrop) ~= "table" or not storage.lowCapDrop then
storage.lowCapDrop = {21175}
end
local useContainer = UI.Container(function(widget, items)
storage.lowCapDrop = items
end, true)
useContainer:setHeight(35)
useContainer:setItems(storage.lowCapDrop)
macro(200, "Drop Items", function()
if not storage.lowCapDrop[1] then return end
if freecap() > 150 then return end
for _, container in pairs(g_game.getContainers()) do
for __, item in ipairs(container:getItems()) do
for i, dropItem in ipairs(storage.lowCapDrop) do
if item:getId() == dropItem.id then
return g_game.move(item, pos(), item:getCount())
end
end
end
end
end)
UI.Separator()

View File

@ -1,367 +0,0 @@
setDefaultTab("HP")
function jewelleryEquip()
panelName = "jewelleryEquipper"
local ui = setupUI([[
Panel
height: 133
margin-top: 2
BotItem
id: ringId
anchors.left: parent.left
anchors.top: parent.top
SmallBotSwitch
id: ringSwitch
anchors.left: ringId.right
anchors.right: parent.right
anchors.top: parent.top
text-align: center
text: Equip Ring
margin-left: 3
margin-right: 45
SmallBotSwitch
id: valueRing
anchors.left: ringSwitch.right
anchors.right: parent.right
anchors.top: parent.top
text-align: center
text: Mana
margin-left: 3
margin-right: 0
BotLabel
id: ringTitle
anchors.left: ringId.right
anchors.right: parent.right
anchors.top: ringId.verticalCenter
text-align: center
HorizontalScrollBar
id: ringScroll1
anchors.left: parent.left
anchors.right: parent.horizontalCenter
anchors.top: ringId.bottom
margin-right: 2
margin-top: 2
minimum: 0
maximum: 100
step: 1
HorizontalScrollBar
id: ringScroll2
anchors.left: parent.horizontalCenter
anchors.right: parent.right
anchors.top: prev.top
margin-left: 2
minimum: 0
maximum: 100
step: 1
BotItem
id: ammyId
anchors.left: parent.left
anchors.top: ringScroll1.bottom
margin-top: 5
SmallBotSwitch
id: ammySwitch
anchors.left: ammyId.right
anchors.right: parent.right
anchors.top: ringScroll2.bottom
text-align: center
text: Equip Amulet
margin-top: 5
margin-left: 3
margin-right: 45
SmallBotSwitch
id: valueAmmy
anchors.left: ammySwitch.right
anchors.right: parent.right
anchors.top: ringScroll2.bottom
text-align: center
text: Mana
margin-top: 5
margin-left: 3
BotLabel
id: ammyTitle
anchors.left: ammyId.right
anchors.right: parent.right
anchors.top: ammyId.verticalCenter
text-align: center
HorizontalScrollBar
id: ammyScroll1
anchors.left: parent.left
anchors.right: parent.horizontalCenter
anchors.top: ammyId.bottom
margin-right: 2
margin-top: 2
minimum: 0
maximum: 100
step: 1
HorizontalScrollBar
id: ammyScroll2
anchors.left: parent.horizontalCenter
anchors.right: parent.right
anchors.top: prev.top
margin-left: 2
minimum: 0
maximum: 100
step: 1
SmallBotSwitch
id: safe
anchors.top: ammyScroll2.bottom
anchors.right: parent.right
anchors.bottom: parent.bottom
text: Safe min
margin-top: 5
width: 60
BotLabel
id: safeText
anchors.top: ammyScroll2.bottom
anchors.left: parent.left
anchors.right: prev.left
anchors.bottom: prev.verticalCenter
text-align: center
text: Stop if below 99%
HorizontalScrollBar
id: safeMin
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: safe.left
anchors.bottom: safe.bottom
margin-left: 2
margin-top: 2
margin-right: 5
minimum: 0
maximum: 99
step: 1
]], parent)
ui:setId(panelName)
if not storage[panelName] or not storage[panelName].ringId or not storage[panelName].ammyId then
storage[panelName] = {
ringSwitch = true,
ammySwitch = true,
ringId = 3048,
ammyId = 3081,
ringMin = 30,
ringMax = 80,
ammyMin = 30,
ammyMax = 80,
valueAmmy = false,
valueRing = false,
ringValue = "HP",
ammyValue = "HP",
safe = true,
safeMin = 30
}
end
if not storage[panelName].safeMin then
storage[panelName].safeMin = 30
end
ui.ringSwitch:setOn(storage[panelName].ringEnabled)
ui.ringSwitch.onClick = function(widget)
storage[panelName].ringEnabled = not storage[panelName].ringEnabled
widget:setOn(storage[panelName].ringEnabled)
end
ui.safe:setOn(storage[panelName].safe)
ui.safe.onClick = function(widget)
storage[panelName].safe = not storage[panelName].safe
widget:setOn(storage[panelName].safe)
end
ui.ammySwitch:setOn(storage[panelName].ammyEnabled)
ui.ammySwitch.onClick = function(widget)
storage[panelName].ammyEnabled = not storage[panelName].ammyEnabled
widget:setOn(storage[panelName].ammyEnabled)
end
local updateRingText = function()
ui.ringTitle:setText("" .. storage[panelName].ringMin .. "% <= " .. storage[panelName].ringValue .. " >= " .. storage[panelName].ringMax .. "%")
end
local updateAmmyText = function()
ui.ammyTitle:setText("" .. storage[panelName].ammyMin .. "% <= " .. storage[panelName].ammyValue .. " >= " .. storage[panelName].ammyMax .. "%")
end
local updateSafeText = function()
ui.safeText:setText("Stop if below " .. storage[panelName].safeMin .. "%")
end
updateSafeText()
ui.valueRing:setOn(storage[panelName].valueRing)
ui.valueRing.onClick = function(widget)
storage[panelName].valueRing = not storage[panelName].valueRing
widget:setOn(storage[panelName].valueRing)
if storage[panelName].valueRing then
storage[panelName].ringValue = "MP"
else
storage[panelName].ringValue = "HP"
end
updateRingText()
end
ui.valueAmmy:setOn(storage[panelName].valueAmmy)
ui.valueAmmy.onClick = function(widget)
storage[panelName].valueAmmy = not storage[panelName].valueAmmy
widget:setOn(storage[panelName].valueAmmy)
if storage[panelName].valueAmmy then
storage[panelName].ammyValue = "MP"
else
storage[panelName].ammyValue = "HP"
end
updateAmmyText()
end
ui.ringScroll1.onValueChange = function(scroll, value)
storage[panelName].ringMin = value
updateRingText()
end
ui.ringScroll2.onValueChange = function(scroll, value)
storage[panelName].ringMax = value
updateRingText()
end
ui.ammyScroll1.onValueChange = function(scroll, value)
storage[panelName].ammyMin = value
updateAmmyText()
end
ui.ammyScroll2.onValueChange = function(scroll, value)
storage[panelName].ammyMax = value
updateAmmyText()
end
ui.ringId.onItemChange = function(widget)
storage[panelName].ringId = widget:getItemId()
end
ui.ammyId.onItemChange = function(widget)
storage[panelName].ammyId = widget:getItemId()
end
ui.safeMin.onValueChange = function(scroll, value)
storage[panelName].safeMin = value
updateSafeText()
end
ui.ringScroll1:setValue(storage[panelName].ringMin)
ui.ringScroll2:setValue(storage[panelName].ringMax)
ui.ammyScroll1:setValue(storage[panelName].ammyMin)
ui.ammyScroll2:setValue(storage[panelName].ammyMax)
ui.ringId:setItemId(storage[panelName].ringId)
ui.ammyId:setItemId(storage[panelName].ammyId)
ui.safeMin:setValue(storage[panelName].safeMin)
local defaultRing
local defaultAmmy
-- basic ring check
function defaultRingFind()
if storage[panelName].ringEnabled then
if getFinger() and (getFinger():getId() ~= storage[panelName].ringId and getFinger():getId() ~= getActiveItemId(storage[panelName].ringId)) then
defaultRing = getInactiveItemId(getFinger():getId())
else
defaultRing = false
end
end
end
-- basic amulet check
function defaultAmmyFind()
if storage[panelName].ammyEnabled then
if getNeck() and (getNeck():getId() ~= storage[panelName].ammyId and getNeck():getId() ~= getActiveItemId(storage[panelName].ammyId)) then
defaultAmmy = getInactiveItemId(getNeck():getId())
else
defaultAmmy = false
end
end
end
local lastAction = now
macro(20, function()
if now - lastAction < math.max(math.max(g_game.getPing()*2,150),300) then return end
if not storage[panelName].ringEnabled and not storage[panelName].ammyEnabled then return end
-- [[ safe findout ]] --
local safeAmmyVal
local safeRingVal
if not storage[panelName].valueAmmy then
safeAmmyVal = hppercent()
else
safeAmmyVal = manapercent()
end
if not storage[panelName].valueRing then
safeRingVal = hppercent()
else
safeRingVal = manapercent()
end
-- [[ condition list ]] --
local ringEnabled = storage[panelName].ringEnabled
local ringEquipped = getFinger() and (getFinger():getId() == storage[panelName].ringId or getFinger():getId() == getActiveItemId(storage[panelName].ringId))
local shouldEquipRing = not storage[panelName].valueRing and hppercent() <= storage[panelName].ringMin or storage[panelName].valueRing and manapercent() <= storage[panelName].ringMin
local shouldUnequipRing = not storage[panelName].valueRing and hppercent() >= storage[panelName].ringMax or storage[panelName].valueRing and manapercent() >= storage[panelName].ringMax
local hasDefaultRing = defaultRing and findItem(defaultRing)
local ammyEnabled = storage[panelName].ammyEnabled
local ammyEquipped = getNeck() and (getNeck():getId() == storage[panelName].ammyId or getNeck():getId() == getActiveItemId(storage[panelName].ammyId))
local shouldEquipAmmy = not storage[panelName].valueAmmy and hppercent() <= storage[panelName].ammyMin or storage[panelName].valueAmmy and manapercent() <= storage[panelName].ammyMin
local shouldUnequipAmmy = not storage[panelName].valueAmmy and hppercent() >= storage[panelName].ammyMax or storage[panelName].valueAmmy and manapercent() >= storage[panelName].ammyMax
local hasDefaultAmmy = defaultAmmy and findItem(defaultAmmy)
local ringIsSafe = not storage[panelName].safe or safeRingVal >= storage[panelName].safeMin
local ammyIsSafe = not storage[panelName].safe or safeAmmyVal >= storage[panelName].safeMin
-- [[ ring ]] --
if ringEnabled then
if not ringEquipped and shouldEquipRing and ringIsSafe then
defaultRingFind()
g_game.equipItemId(storage[panelName].ringId)
lastAction = now
return
elseif ringEquipped and (shouldUnequipRing or not ringIsSafe) then
if hasDefaultRing then
g_game.equipItemId(defaultRing)
lastAction = now
return
else
g_game.equipItemId(storage[panelName].ringId)
lastAction = now
return
end
end
end
-- [[ amulet ]] --
if ammyEnabled then
if not ammyEquipped and shouldEquipAmmy and ammyIsSafe then
defaultAmmyFind()
g_game.equipItemId(storage[panelName].ammyId)
lastAction = now
return
elseif ammyEquipped and (shouldUnequipAmmy or not ammyIsSafe) then
if hasDefaultAmmy then
g_game.equipItemId(defaultAmmy)
lastAction = now
return
else
g_game.equipItemId(storage[panelName].ammyId)
lastAction = now
return
end
end
end
end)
-- end of function
end
if g_game.getClientVersion() >= 1000 then
addSeparator()
UI.Label("-- [[ Equipper ]] --")
addSeparator()
jewelleryEquip()
addSeparator()
end

View File

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

View File

@ -1,209 +0,0 @@
PlayerName < Label
background-color: alpha
text-offset: 2 0
focusable: true
height: 16
$focus:
background-color: #00000055
Button
id: remove
!text: tr('x')
anchors.right: parent.right
margin-right: 15
width: 15
height: 15
PlayerListsWindow < MainWindow
!text: tr('Player Lists')
size: 580 350
@onEscape: self:hide()
Label
anchors.left: FriendList.left
anchors.top: parent.top
anchors.right: FriendList.right
text-align: center
text: Friends List
margin-right: 3
TextList
id: FriendList
anchors.top: parent.top
anchors.left: parent.left
margin-top: 15
margin-bottom: 5
margin-right: 3
padding: 1
width: 180
height: 160
vertical-scrollbar: FriendListScrollBar
VerticalScrollBar
id: FriendListScrollBar
anchors.top: FriendList.top
anchors.bottom: FriendList.bottom
anchors.right: FriendList.right
step: 14
pixels-scroll: true
TextEdit
id: FriendName
anchors.right: FriendList.right
anchors.left: FriendList.left
anchors.top: FriendList.bottom
margin-right: 3
margin-top: 5
Button
id: AddFriend
!text: tr('Add Friend')
anchors.right: FriendList.right
anchors.left: FriendList.left
anchors.top: prev.bottom
margin-right: 3
margin-top: 3
Label
anchors.right: EnemyList.right
anchors.top: parent.top
anchors.left: EnemyList.left
text-align: center
text: Enemy List
margin-left: 3
TextList
id: EnemyList
anchors.top: parent.top
anchors.left: FriendList.right
margin-top: 15
margin-bottom: 5
margin-left: 3
padding: 1
width: 180
height: 160
vertical-scrollbar: EnemyListScrollBar
VerticalScrollBar
id: EnemyListScrollBar
anchors.top: EnemyList.top
anchors.bottom: EnemyList.bottom
anchors.right: EnemyList.right
step: 14
pixels-scroll: true
TextEdit
id: EnemyName
anchors.left: EnemyList.left
anchors.right: EnemyList.right
anchors.top: EnemyList.bottom
margin-left: 3
margin-top: 5
Button
id: AddEnemy
!text: tr('Add Enemy')
anchors.left: EnemyList.left
anchors.right: EnemyList.right
anchors.top: prev.bottom
margin-left: 3
margin-top: 3
Label
anchors.right: BlackList.right
anchors.top: parent.top
anchors.left: BlackList.left
text-align: center
text: Anty RS List
margin-left: 3
TextList
id: BlackList
anchors.top: parent.top
anchors.left: EnemyList.right
margin-top: 15
margin-bottom: 5
margin-left: 3
padding: 1
width: 180
height: 160
vertical-scrollbar: BlackListScrollBar
VerticalScrollBar
id: BlackListScrollBar
anchors.top: BlackList.top
anchors.bottom: BlackList.bottom
anchors.right: BlackList.right
step: 14
pixels-scroll: true
TextEdit
id: BlackName
anchors.left: BlackList.left
anchors.right: BlackList.right
anchors.top: BlackList.bottom
margin-left: 3
margin-top: 5
Button
id: AddBlack
!text: tr('Add Anty-RS')
anchors.left: BlackList.left
anchors.right: BlackList.right
anchors.top: prev.bottom
margin-left: 3
margin-top: 3
BotSwitch
id: Members
anchors.left: parent.left
anchors.top: AddEnemy.bottom
margin-top: 15
width: 135
text-align: center
text: Group Members
BotSwitch
id: Outfit
anchors.bottom: prev.bottom
anchors.left: prev.right
margin-left: 3
width: 135
text-align: center
text: Color Outfits
BotSwitch
id: Marks
anchors.bottom: prev.bottom
anchors.left: prev.right
width: 135
margin-left: 3
text-align: center
text: Not Ally = Enemy
BotSwitch
id: Highlight
anchors.bottom: prev.bottom
anchors.left: prev.right
width: 135
margin-left: 3
text-align: center
text: Highlight
HorizontalSeparator
id: separator
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

@ -1,265 +0,0 @@
setDefaultTab("Main")
local panelName = "playerList"
local ui = setupUI([[
Panel
height: 18
Button
id: editList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
background: #292A2A
height: 18
text: Player Lists
]], parent)
ui:setId(panelName)
if not storage[panelName] then
storage[panelName] = {
enemyList = {},
friendList = {},
blackList = {},
groupMembers = true,
outfits = false,
marks = false,
highlight = false
}
end
local config = storage[panelName]
-- for backward compability
if not config.blackList then
config.blackList = {}
end
-- functions
local function clearCachedPlayers()
CachedFriends = {}
CachedEnemies = {}
end
local refreshStatus = function()
for _, spec in ipairs(getSpectators()) do
if spec:isPlayer() and not spec:isLocalPlayer() then
if config.outfits then
local specOutfit = spec:getOutfit()
if isFriend(spec:getName()) then
if config.highlight then
spec:setMarked('#0000FF')
end
specOutfit.head = 88
specOutfit.body = 88
specOutfit.legs = 88
specOutfit.feet = 88
if storage.BOTserver.outfit then
local voc = vBot.BotServerMembers[spec:getName()]
specOutfit.addons = 3
if voc == 1 then
specOutfit.type = 131
elseif voc == 2 then
specOutfit.type = 129
elseif voc == 3 then
specOutfit.type = 130
elseif voc == 4 then
specOutfit.type = 144
end
end
spec:setOutfit(specOutfit)
elseif isEnemy(spec:getName()) then
if config.highlight then
spec:setMarked('#FF0000')
end
specOutfit.head = 94
specOutfit.body = 94
specOutfit.legs = 94
specOutfit.feet = 94
spec:setOutfit(specOutfit)
end
end
end
end
end
refreshStatus()
local checkStatus = function(creature)
if not creature:isPlayer() or creature:isLocalPlayer() then return end
local specName = creature:getName()
local specOutfit = creature:getOutfit()
if isFriend(specName) then
if config.highlight then
creature:setMarked('#0000FF')
end
if config.outfits then
specOutfit.head = 88
specOutfit.body = 88
specOutfit.legs = 88
specOutfit.feet = 88
if storage.BOTserver.outfit then
local voc = vBot.BotServerMembers[creature:getName()]
specOutfit.addons = 3
if voc == 1 then
specOutfit.type = 131
elseif voc == 2 then
specOutfit.type = 129
elseif voc == 3 then
specOutfit.type = 130
elseif voc == 4 then
specOutfit.type = 144
end
end
creature:setOutfit(specOutfit)
end
elseif isEnemy(specName) then
if config.highlight then
creature:setMarked('#FF0000')
end
if config.outfits then
specOutfit.head = 94
specOutfit.body = 94
specOutfit.legs = 94
specOutfit.feet = 94
creature:setOutfit(specOutfit)
end
end
end
-- eof
-- UI
rootWidget = g_ui.getRootWidget()
playerListWindow = UI.createWindow('PlayerListsWindow', rootWidget)
playerListWindow:hide()
playerListWindow.Members:setOn(config.groupMembers)
playerListWindow.Members.onClick = function(widget)
config.groupMembers = not config.groupMembers
if not config then
clearCachedPlayers()
end
refreshStatus()
widget:setOn(config.groupMembers)
end
playerListWindow.Outfit:setOn(config.outfits)
playerListWindow.Outfit.onClick = function(widget)
config.outfits = not config.outfits
widget:setOn(config.outfits)
end
playerListWindow.Marks:setOn(config.marks)
playerListWindow.Marks.onClick = function(widget)
config.marks = not config.marks
widget:setOn(config.marks)
end
playerListWindow.Highlight:setOn(config.highlight)
playerListWindow.Highlight.onClick = function(widget)
config.highlight = not config.highlight
widget:setOn(config.highlight)
end
if config.enemyList and #config.enemyList > 0 then
for _, name in ipairs(config.enemyList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
label.remove.onClick = function(widget)
table.removevalue(config.enemyList, label:getText())
label:destroy()
end
label:setText(name)
end
end
if config.blackList and #config.blackList > 0 then
for _, name in ipairs(config.blackList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.BlackList)
label.remove.onClick = function(widget)
table.removevalue(config.blackList, label:getText())
label:destroy()
end
label:setText(name)
end
end
if config.friendList and #config.friendList > 0 then
for _, name in ipairs(config.friendList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
label.remove.onClick = function(widget)
table.removevalue(config.friendList, label:getText())
label:destroy()
end
label:setText(name)
end
end
playerListWindow.AddFriend.onClick = function(widget)
local friendName = playerListWindow.FriendName:getText()
if friendName:len() > 0 and not table.contains(config.friendList, friendName, true) then
table.insert(config.friendList, friendName)
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
label.remove.onClick = function(widget)
table.removevalue(config.friendList, label:getText())
label:destroy()
end
label:setText(friendName)
playerListWindow.FriendName:setText('')
clearCachedPlayers()
refreshStatus()
end
end
playerListWindow.AddEnemy.onClick = function(widget)
local enemyName = playerListWindow.EnemyName:getText()
if enemyName:len() > 0 and not table.contains(config.enemyList, enemyName, true) then
table.insert(config.enemyList, enemyName)
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
label.remove.onClick = function(widget)
table.removevalue(config.enemyList, label:getText())
label:destroy()
end
label:setText(enemyName)
playerListWindow.EnemyName:setText('')
clearCachedPlayers()
refreshStatus()
end
end
playerListWindow.AddBlack.onClick = function(widget)
local blackName = playerListWindow.BlackName:getText()
if blackName:len() > 0 and not table.contains(config.blackList, blackName, true) then
table.insert(config.blackList, blackName)
local label = g_ui.createWidget("PlayerName", playerListWindow.BlackList)
label.remove.onClick = function(widget)
table.removevalue(config.blackList, label:getText())
label:destroy()
end
label:setText(blackName)
playerListWindow.BlackName:setText('')
clearCachedPlayers()
refreshStatus()
end
end
ui.editList.onClick = function(widget)
playerListWindow:show()
playerListWindow:raise()
playerListWindow:focus()
end
playerListWindow.closeButton.onClick = function(widget)
playerListWindow:hide()
end
-- execution
onCreatureAppear(function(creature)
checkStatus(creature)
end)
onPlayerPositionChange(function(x,y)
if x.z ~= y.z then
schedule(20, function()
refreshStatus()
end)
end
end)

View File

@ -1,311 +0,0 @@
function SuppliesPanel(parent)
local panelName = "supplies"
if not parent then
parent = panel
end
if not SuppliesConfig[panelName] then
SuppliesConfig[panelName] = {
item1 = 0,
item2 = 0,
item3 = 0,
item4 = 0,
item5 = 0,
item6 = 0,
item7 = 0,
capValue = 0,
capSwitch = false,
SoftBoots = false,
staminaSwitch = false,
staminaValue = 900,
imbues = false,
item1Min = 0,
item1Max = 0,
item2Min = 0,
item2Max = 0,
item3Min = 0,
item3Max = 0,
item4Min = 0,
item4Max = 0,
item5Min = 0,
item5Max = 0,
item6Min = 0,
item6Max = 0,
item7Max = 0,
sortSupplies = false,
potionBp = 0,
runeBp = 0,
ammoBp = 0
}
end
local config = SuppliesConfig[panelName]
-- data validation
local setup = config
setup.item1 = setup.item1 or 0
setup.item2 = setup.item2 or 0
setup.item3 = setup.item3 or 0
setup.item4 = setup.item4 or 0
setup.item5 = setup.item5 or 0
setup.item6 = setup.item6 or 0
setup.item1Min = setup.item1Min or 0
setup.item1Max = setup.item1Max or 0
setup.item2Min = setup.item2Min or 0
setup.item2Max = setup.item2Max or 0
setup.item3Min = setup.item3Min or 0
setup.item3Max = setup.item3Max or 0
setup.item4Min = setup.item4Min or 0
setup.item4Max = setup.item4Max or 0
setup.item5Min = setup.item5Min or 0
setup.item5Max = setup.item5Max or 0
setup.item6Min = setup.item6Min or 0
setup.item6Max = setup.item6Max or 0
setup.capValue = setup.capValue or 0
setup.staminaValue = setup.staminaValue or 0
rootWidget = g_ui.getRootWidget()
if rootWidget then
SuppliesWindow = g_ui.createWidget('SuppliesWindow', rootWidget)
SuppliesWindow:hide()
SuppliesWindow.capSwitch:setOn(config.capSwitch)
SuppliesWindow.capSwitch.onClick = function(widget)
config.capSwitch = not config.capSwitch
widget:setOn(config.capSwitch)
end
SuppliesWindow.SoftBoots:setOn(config.SoftBoots)
SuppliesWindow.SoftBoots.onClick = function(widget)
config.SoftBoots = not config.SoftBoots
widget:setOn(config.SoftBoots)
end
SuppliesWindow.imbues:setOn(config.imbues)
SuppliesWindow.imbues.onClick = function(widget)
config.imbues = not config.imbues
widget:setOn(config.imbues)
end
SuppliesWindow.staminaSwitch:setOn(config.staminaSwitch)
SuppliesWindow.staminaSwitch.onClick = function(widget)
config.staminaSwitch = not config.staminaSwitch
widget:setOn(config.staminaSwitch)
end
-- bot items
SuppliesWindow.item1:setItemId(config.item1)
SuppliesWindow.item1.onItemChange = function(widget)
config.item1 = widget:getItemId()
end
SuppliesWindow.item2:setItemId(config.item2)
SuppliesWindow.item2.onItemChange = function(widget)
config.item2 = widget:getItemId()
end
SuppliesWindow.item3:setItemId(config.item3)
SuppliesWindow.item3.onItemChange = function(widget)
config.item3 = widget:getItemId()
end
SuppliesWindow.item4:setItemId(config.item4)
SuppliesWindow.item4.onItemChange = function(widget)
config.item4 = widget:getItemId()
end
SuppliesWindow.item5:setItemId(config.item5)
SuppliesWindow.item5.onItemChange = function(widget)
config.item5 = widget:getItemId()
end
SuppliesWindow.item6:setItemId(config.item6)
SuppliesWindow.item6.onItemChange = function(widget)
config.item6 = widget:getItemId()
end
-- text windows
SuppliesWindow.capValue:setText(config.capValue)
SuppliesWindow.capValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.capValue:getText())
if not value then
SuppliesWindow.capValue:setText(0)
config.capValue = 0
else
text = text:match("0*(%d+)")
config.capValue = text
end
end
SuppliesWindow.item1Min:setText(config.item1Min)
SuppliesWindow.item1Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item1Min:getText())
if not value then
SuppliesWindow.item1Min:setText(0)
config.item1Min = 0
else
text = text:match("0*(%d+)")
config.item1Min = text
end
end
SuppliesWindow.item1Max:setText(config.item1Max)
SuppliesWindow.item1Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item1Max:getText())
if not value then
SuppliesWindow.item1Max:setText(0)
config.item1Max = 0
else
text = text:match("0*(%d+)")
config.item1Max = text
end
end
SuppliesWindow.item2Min:setText(config.item2Min)
SuppliesWindow.item2Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item2Min:getText())
if not value then
SuppliesWindow.item2Min:setText(0)
config.item2Min = 0
else
text = text:match("0*(%d+)")
config.item2Min = text
end
end
SuppliesWindow.item2Max:setText(config.item2Max)
SuppliesWindow.item2Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item2Max:getText())
if not value then
SuppliesWindow.item2Max:setText(0)
config.item2Max = 0
else
text = text:match("0*(%d+)")
config.item2Max = text
end
end
SuppliesWindow.item3Min:setText(config.item3Min)
SuppliesWindow.item3Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item3Min:getText())
if not value then
SuppliesWindow.item3Min:setText(0)
config.item3Min = 0
else
text = text:match("0*(%d+)")
config.item3Min = text
end
end
SuppliesWindow.item3Max:setText(config.item3Max)
SuppliesWindow.item3Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item3Max:getText())
if not value then
SuppliesWindow.item3Max:setText(0)
config.item3Max = 0
else
config.item3Max = text
end
end
SuppliesWindow.item4Min:setText(config.item4Min)
SuppliesWindow.item4Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item4Min:getText())
if not value then
SuppliesWindow.item4Min:setText(0)
config.item4Min = 0
else
text = text:match("0*(%d+)")
config.item4Min = text
end
end
SuppliesWindow.staminaValue:setText(config.staminaValue)
SuppliesWindow.staminaValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.staminaValue:getText())
if not value then
SuppliesWindow.staminaValue:setText(0)
config.staminaValue = 0
else
text = text:match("0*(%d+)")
config.staminaValue = text
end
end
SuppliesWindow.item4Max:setText(config.item4Max)
SuppliesWindow.item4Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item4Max:getText())
if not value then
SuppliesWindow.item4Max:setText(0)
config.item4Max = 0
else
text = text:match("0*(%d+)")
config.item4Max = text
end
end
SuppliesWindow.item5Min:setText(config.item5Min)
SuppliesWindow.item5Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Min:getText())
if not value then
SuppliesWindow.item5Min:setText(0)
config.item5Min = 0
else
text = text:match("0*(%d+)")
config.item5Min = text
end
end
SuppliesWindow.item5Max:setText(config.item5Max)
SuppliesWindow.item5Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Max:getText())
if not value then
SuppliesWindow.item5Max:setText(0)
config.item5Max = 0
else
text = text:match("0*(%d+)")
config.item5Max = text
end
end
SuppliesWindow.item6Min:setText(config.item6Min)
SuppliesWindow.item6Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Min:getText())
if not value then
SuppliesWindow.item6Min:setText(0)
config.item6Min = 0
else
text = text:match("0*(%d+)")
config.item6Min = text
end
end
SuppliesWindow.item6Max:setText(config.item6Max)
SuppliesWindow.item6Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Max:getText())
if not value then
SuppliesWindow.item6Max:setText(0)
config.item6Max = 0
else
text = text:match("0*(%d+)")
config.item6Max = text
end
end
end
UI.Button("Supplies", function()
SuppliesWindow:show()
SuppliesWindow:raise()
SuppliesWindow:focus()
end)
SuppliesWindow.close.onClick = function(widget)
SuppliesWindow:hide()
vBotConfigSave("supply")
end
end
UI.Separator()
SuppliesPanel(setDefaultTab("Cave"))

View File

@ -31,7 +31,7 @@ local luaFiles = {
"pushmax",
"combo",
"HealBot",
"Sio",
"new healer",
"AttackBot", -- last of major modules
"ingame_editor",
"Dropper",
@ -48,7 +48,9 @@ local luaFiles = {
"spy_level",
"supplies",
"depositer_config",
"npc_talk"
"npc_talk",
"xeno_menu",
"hold_target"
}
for i, file in ipairs(luaFiles) do

View File

@ -3,6 +3,7 @@ CaveBot.Extensions.BuySupplies = {}
CaveBot.Extensions.BuySupplies.setup = function()
CaveBot.registerAction("BuySupplies", "#C300FF", function(value, retries)
local supplies = SuppliesConfig.supplies
supplies = supplies[supplies.currentProfile]
local item1Count = itemAmount(supplies.item1)
local item2Count = itemAmount(supplies.item2)
local item3Count = itemAmount(supplies.item3)

View File

@ -236,6 +236,60 @@ CaveBot.gotoNextWaypointInRange = function()
return false
end
local function reverseTable(t, max)
local reversedTable = {}
local itemCount = max or #t
for i, v in ipairs(t) do
reversedTable[itemCount + 1 - i] = v
end
return reversedTable
end
function rpairs(t)
test()
return function(t, i)
i = i - 1
if i ~= 0 then
return i, t[i]
end
end, t, #t + 1
end
CaveBot.gotoFirstPreviousReachableWaypoint = function()
local currentAction = ui.list:getFocusedChild()
local currentIndex = ui.list:getChildIndex(currentAction)
local index = ui.list:getChildIndex(currentAction)
-- check up to 100 childs
for i=0,100 do
index = index - i
if index <= 0 or index > currentIndex or math.abs(index-currentIndex) > 100 then
break
end
local child = ui.list:getChildByIndex(index)
if child then
local text = child:getText()
if string.starts(text, "goto:") then
local re = regexMatch(text, [[(?:goto:)([^,]+),([^,]+),([^,]+)]])
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
if posz() == pos.z then
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then
print("found pos, going back "..currentIndex-index.. " waypoints.")
return ui.list:focusChild(child)
end
end
end
end
end
-- not found
print("previous pos not found, proceeding")
return false
end
CaveBot.getFirstWaypointBeforeLabel = function(label)
label = "label:"..label
label = label:lower()

View File

@ -42,7 +42,7 @@ CaveBot.Extensions.ClearTile.setup = function()
end
if retries > 0 then
delay(1100)
delay(1500)
end
-- but if not then first check for creatures
@ -55,7 +55,7 @@ CaveBot.Extensions.ClearTile.setup = function()
elseif c:isPlayer() then
local candidates = {}
for _, tile in ipairs(g_map.getTiles(posz())) do
if getDistanceBetween(c:getPosition(), tile:getPosition()) == 1 and tile:getPosition() ~= pPos then
if getDistanceBetween(c:getPosition(), tile:getPosition()) == 1 and tile:getPosition() ~= pPos and tile:isWalkable(false) then
table.insert(candidates, tile:getPosition())
end
end
@ -65,7 +65,11 @@ CaveBot.Extensions.ClearTile.setup = function()
return false
else
print("CaveBot[ClearTile]: pushing player... " .. c:getName() .. " out of the way")
g_game.move(c, candidates[math.random(1,#candidates)])
local pos = candidates[math.random(1,#candidates)]
local tile = g_map.getTile(pos)
tile:setText("here")
schedule(500, function() tile:setText("") end)
g_game.move(c, pos)
return "retry"
end
end

View File

@ -24,6 +24,7 @@ CaveBot.Extensions.DWithdraw.setup = function()
capLimit = tonumber(data[4]:trim())
end
-- cap check
if freecap() < (capLimit or 200) then
for i, container in ipairs(getContainers()) do

View File

@ -15,6 +15,17 @@ local function resetCache()
g_game.close(container)
end
end
if storage.caveBot.backStop then
storage.caveBot.backStop = false
CaveBot.setOff()
elseif storage.caveBot.backTrainers then
storage.caveBot.backTrainers = false
CaveBot.gotoLabel('toTrainers')
elseif storage.caveBot.backOffline then
storage.caveBot.backOffline = false
CaveBot.gotoLabel('toOfflineTraining')
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"
@ -23,6 +34,7 @@ CaveBot.Extensions.Depositor.setup = function()
CaveBot.registerAction("depositor", "#002FFF", function(value, retries)
-- version check, TODO old tibia
if g_game.getClientVersion() < 960 then
resetCache()
warn("CaveBot[Depositor]: unsupported Tibia version, will be added in near future")
return false
end
@ -120,5 +132,6 @@ CaveBot.Extensions.Depositor.setup = function()
value="no",
title="Depositor",
description=description,
validation="(yes|Yes|YES|no|No|NO)"
})
end

View File

@ -53,5 +53,6 @@ CaveBot.Extensions.OpenDoors.setup = function()
title="Door position",
description="doors position (x,y,z) and key id (optional)",
multiline=false,
validation=[[\d{1,5},\d{1,5},\d{1,2}(?:,\d{1,5}$|$)]]
})
end

View File

@ -76,9 +76,10 @@ CaveBot.Extensions.Imbuing.setup = function()
if not item then
-- did try before, still not found so item is unavailable
if triedToTakeOff then
warn("CaveBot[Imbuing] item not found! proceeding")
reset()
return false
warn("CaveBot[Imbuing] item not found! skipping: "..currentId)
triedToTakeOff = false
currentIndex = currentIndex + 1
return "retry"
end
triedToTakeOff = true
g_game.equipItemId(currentId)
@ -99,7 +100,7 @@ CaveBot.Extensions.Imbuing.setup = function()
useWith(shrine, item)
currentIndex = currentIndex + 1
warn("CaveBot[Imbuing] Using shrine on item: "..currentId)
delay(2000)
delay(4000)
return "retry"
end)

View File

@ -24,5 +24,6 @@ CaveBot.Extensions.Lure.setup = function()
title="Lure",
description="TargetBot: start, stop, toggle",
multiline=false,
validation=[[(start|stop|toggle)$]]
})
end

View File

@ -26,16 +26,20 @@ CaveBot.Extensions.PosCheck.setup = function()
return true
else
posCheckRetries = posCheckRetries + 1
if data[1] == "last" then
CaveBot.gotoFirstPreviousReachableWaypoint()
print("CaveBot[CheckPos]: position not-reached, going back to first reachable waypoint.")
return false
else
CaveBot.gotoLabel(data[1])
print("CaveBot[CheckPos]: position not-reached, going back to label: " .. data[1])
return false
end
end
end)
CaveBot.Editor.registerAction("poscheck", "pos check", {
value=function() return "label" .. "," .. "10" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
value=function() return "last" .. "," .. "10" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
title="Location Check",
description="label name, accepted dist from coordinates, x, y, z",
multiline=false,

View File

@ -60,5 +60,6 @@ CaveBot.Extensions.SellAll.setup = function()
value="NPC",
title="Sell All",
description="Insert NPC name, and 'yes' if sell with delay ",
validation=[[^[^,]+(?:, yes$|, Yes$|, YES$|$)]]
})
end

View File

@ -35,6 +35,7 @@ CaveBot.Extensions.SupplyCheck.setup = function()
time = now
local supplies = SuppliesConfig.supplies
supplies = supplies[supplies.currentProfile]
local softCount = itemAmount(6529) + itemAmount(3549)
local totalItem1 = itemAmount(supplies.item1)
local totalItem2 = itemAmount(supplies.item2)
@ -43,7 +44,28 @@ CaveBot.Extensions.SupplyCheck.setup = function()
local totalItem5 = itemAmount(supplies.item5)
local totalItem6 = itemAmount(supplies.item6)
if supplyRetries > (storage.extras.huntRoutes or 50) then
if storage.caveBot.forceRefill then
print("CaveBot[SupplyCheck]: User forced, going back on refill. Last round took: " .. round)
storage.caveBot.forceRefill = false
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backStop then
print("CaveBot[SupplyCheck]: User forced, going back to city and turning off CaveBot. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backTrainers then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on trainers. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backOffline then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on offline training. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif supplyRetries > (storage.extras.huntRoutes or 50) then
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
@ -115,5 +137,6 @@ CaveBot.Extensions.SupplyCheck.setup = function()
value=function() return "startHunt," .. posx() .. "," .. posy() .. "," .. posz() end,
title="Supply check label",
description="Insert here hunting start label",
validation=[[[^,]+,\d{1,5},\d{1,5},\d{1,2}$]]
})
end

View File

@ -145,8 +145,10 @@ TargetBot.Creature.walk = function(creature, config, targets)
delayFrom = config.delayFrom
-- luring
if config.closeLure and config.closeLureAmount <= getMonsters(1) then
return TargetBot.allowCaveBot(150)
end
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
if targetBotLure then
anchorPosition = nil
return TargetBot.allowCaveBot(150)
@ -165,11 +167,10 @@ TargetBot.Creature.walk = function(creature, config, targets)
end
end
local lastRePosition = now
if not config.chase and not config.keepDistance and config.rePosition and (creature:getHealthPercent() >= storage.extras.killUnder) then
local currentDistance = findPath(pos, cpos, 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true})
if (not config.chase or #currentDistance == 1) and not config.avoidAttacks 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})
if ((storage.extras.killUnder > 1 and (creature:getHealthPercent() < storage.extras.killUnder)) or config.chase) and not config.keepDistance then
if #currentDistance > 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1})
@ -237,7 +238,8 @@ onPlayerPositionChange(function(newPos, oldPos)
if TargetBot.isOff() then return end
if not lureMax then return end
if storage.TargetBotDelayWhenPlayer then return end
if not dynamicLureDelay then return end
if dynamicLureDelay and targetCount < (delayFrom or 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)
end)

View File

@ -87,6 +87,7 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
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)
addScrollBar("closeLureAmount", "Close Pull Until", 0, 8, 3)
addCheckBox("chase", "Chase", true)
addCheckBox("keepDistance", "Keep Distance", false)
@ -100,4 +101,5 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
addCheckBox("dynamicLureDelay", "Dynamic lure delay", false)
addCheckBox("diamondArrows", "D-Arrows priority", false)
addCheckBox("rePosition", "rePosition to better tile", false)
addCheckBox("closeLure", "Close Pulling Monsters", false)
end

View File

@ -313,6 +313,13 @@ onCreatureDisappear(function(creature)
if not container or not container:isContainer() then return end
if not findPath(player:getPosition(), mpos, 6, {ignoreNonPathable=true, ignoreCreatures=true, ignoreCost=true}) then return end
table.insert(TargetBot.Looting.list, {pos=mpos, creature=name, container=container:getId(), added=now, tries=0})
table.sort(TargetBot.Looting.list, function(a,b)
a.dist = distanceFromPlayer(a.pos)
b.dist = distanceFromPlayer(b.pos)
return a.dist > b.dist
end)
container:setMarked('#000088')
end)
end)

View File

@ -181,6 +181,10 @@ TargetBot.setStatus = function(text)
return ui.status.right:setText(text)
end
TargetBot.getStatus = function()
return ui.status.right:getText()
end
TargetBot.isOn = function()
return config.isOn()
end

View File

@ -7,6 +7,7 @@ local showItem = false
local category = 1
local patternCategory = 1
local pattern = 1
local mainWindow
-- label library
@ -614,32 +615,40 @@ ui.title.onClick = function(widget)
end
ui.settings.onClick = function(widget)
windowUI:show()
windowUI:raise()
windowUI:focus()
mainWindow:show()
mainWindow:raise()
mainWindow:focus()
end
rootWidget = g_ui.getRootWidget()
if rootWidget then
windowUI = UI.createWindow("AttackBotWindow", rootWidget)
windowUI:hide()
mainWindow = UI.createWindow("AttackBotWindow")
mainWindow:hide()
local panel = windowUI.mainPanel
local settingsUI = windowUI.settingsPanel
local panel = mainWindow.mainPanel
local settingsUI = mainWindow.settingsPanel
mainWindow.onVisibilityChange = function(widget, visible)
if not visible then
currentSettings.attackTable = {}
for i, child in ipairs(panel.entryList:getChildren()) do
table.insert(currentSettings.attackTable, child.params)
end
vBotConfigSave("atk")
end
end
-- main panel
-- functions
function toggleSettings()
panel:setVisible(not showSettings)
windowUI.shooterLabel:setVisible(not showSettings)
mainWindow.shooterLabel:setVisible(not showSettings)
settingsUI:setVisible(showSettings)
windowUI.settingsLabel:setVisible(showSettings)
windowUI.settings:setText(showSettings and "Back" or "Settings")
mainWindow.settingsLabel:setVisible(showSettings)
mainWindow.settings:setText(showSettings and "Back" or "Settings")
end
toggleSettings()
windowUI.settings.onClick = function()
mainWindow.settings.onClick = function()
showSettings = not showSettings
toggleSettings()
end
@ -717,55 +726,53 @@ if rootWidget then
-- eo in/de/crementation
------- [[core table function]] -------
-- refreshing values
function refreshAttacks()
if not currentSettings.attackTable then return end
function setupWidget(widget)
local params = widget.params
for i, child in pairs(panel.entryList:getChildren()) do child:destroy() end
for i, entry in pairs(currentSettings.attackTable) do
local label = UI.createWidget("AttackEntry", panel.entryList)
label:setText(entry.description)
label:setTooltip(entry.tooltip)
label.remove.onClick = function(widget)
table.remove(currentSettings.attackTable, i)
label:destroy()
widget:setText(params.description)
if params.itemId > 0 then
widget.spell:setVisible(false)
widget.id:setVisible(true)
widget.id:setItemId(params.itemId)
end
widget:setTooltip(params.tooltip)
widget.remove.onClick = function()
panel.up:setEnabled(false)
panel.down:setEnabled(false)
refreshAttacks()
widget:destroy()
end
label.enabled:setChecked(entry.enabled)
label.enabled.onClick = function(widget)
entry.enabled = not entry.enabled
label.enabled:setChecked(entry.enabled)
widget.enabled:setChecked(params.enabled)
widget.enabled.onClick = function()
params.enabled = not params.enabled
widget.enabled:setChecked(params.enabled)
end
-- will serve as edit
label.onDoubleClick = function(widget)
table.remove(currentSettings.attackTable, i)
label:destroy()
panel.manaPercent:setValue(entry.mana)
panel.creatures:setValue(entry.count)
panel.minHp:setValue(entry.minHp)
panel.maxHp:setValue(entry.maxHp)
panel.cooldown:setValue(entry.cooldown)
showItem = entry.itemId > 100 and true or false
panel.itemId:setItemId(entry.itemId)
panel.spellName:setText(entry.spell or "")
panel.orMore:setChecked(entry.orMore)
widget.onDoubleClick = function(widget)
panel.manaPercent:setValue(params.mana)
panel.creatures:setValue(params.count)
panel.minHp:setValue(params.minHp)
panel.maxHp:setValue(params.maxHp)
panel.cooldown:setValue(params.cooldown)
showItem = params.itemId > 100 and true or false
panel.itemId:setItemId(params.itemId)
panel.spellName:setText(params.spell or "")
panel.orMore:setChecked(params.orMore)
toggleItem()
category = entry.category
patternCategory = entry.patternCategory
pattern = entry.pattern
category = params.category
patternCategory = params.patternCategory
pattern = params.pattern
setPatternText()
setCategoryText()
widget:destroy()
end
label.onClick = function(widget)
widget.onClick = function(widget)
if #panel.entryList:getChildren() == 1 then
panel.up:setEnabled(false)
panel.down:setEnabled(false)
elseif panel.entryList:getChildIndex(panel.entryList:getFocusedChild()) == 1 then
elseif panel.entryList:getChildIndex(widget) == 1 then
panel.up:setEnabled(false)
panel.down:setEnabled(true)
elseif panel.entryList:getChildIndex(panel.entryList:getFocusedChild()) == #panel.entryList:getChildren() then
elseif panel.entryList:getChildIndex(widget) == panel.entryList:getChildCount() then
panel.up:setEnabled(true)
panel.down:setEnabled(false)
else
@ -774,6 +781,18 @@ if rootWidget then
end
end
end
-- refreshing values
function refreshAttacks()
if not currentSettings.attackTable then return end
panel.entryList:destroyChildren()
for i, entry in pairs(currentSettings.attackTable) do
local label = UI.createWidget("AttackEntry", panel.entryList)
label.params = entry
setupWidget(label)
end
end
refreshAttacks()
panel.up:setEnabled(false)
@ -810,7 +829,7 @@ if rootWidget then
local countDescription = orMore and count.."+" or count
local entry = {
local params = {
creatures = creatures,
monsters = monsters,
mana = mana,
@ -829,32 +848,36 @@ if rootWidget then
description = '['..type..'] '..countDescription.. ' '..specificMonsters..': '..attackType..', '..categoryName..' ('..minHp..'%-'..maxHp..'%)'
}
-- inserting to table
table.insert(currentSettings.attackTable, entry)
refreshAttacks()
local label = UI.createWidget("AttackEntry", panel.entryList)
label.params = params
setupWidget(label)
resetFields()
end
-- moving values
-- up
panel.up.onClick = function(widget)
local n = panel.entryList:getChildIndex(panel.entryList:getFocusedChild())
local t = currentSettings.attackTable
local focused = panel.entryList:getFocusedChild()
local n = panel.entryList:getChildIndex(focused)
t[n], t[n-1] = t[n-1], t[n]
panel.up:setEnabled(false)
panel.down:setEnabled(false)
refreshAttacks()
if n-1 == 1 then
widget:setEnabled(false)
end
panel.down:setEnabled(true)
panel.entryList:moveChildToIndex(focused, n-1)
panel.entryList:ensureChildVisible(focused)
end
-- down
panel.down.onClick = function(widget)
local n = panel.entryList:getChildIndex(panel.entryList:getFocusedChild())
local t = currentSettings.attackTable
local focused = panel.entryList:getFocusedChild()
local n = panel.entryList:getChildIndex(focused)
t[n], t[n+1] = t[n+1], t[n]
panel.up:setEnabled(false)
panel.down:setEnabled(false)
refreshAttacks()
if n + 1 == panel.entryList:getChildCount() then
widget:setEnabled(false)
end
panel.up:setEnabled(true)
panel.entryList:moveChildToIndex(focused, n+1)
panel.entryList:ensureChildVisible(focused)
end
-- [[settings panel]] --
@ -907,12 +930,11 @@ if rootWidget then
-- window elements
windowUI.closeButton.onClick = function()
mainWindow.closeButton.onClick = function()
showSettings = false
toggleSettings()
resetFields()
windowUI:hide()
vBotConfigSave("atk")
mainWindow:hide()
end
-- core functions
@ -1020,7 +1042,13 @@ if rootWidget then
profileChange()
end
end
end
AttackBot.show = function()
mainWindow:show()
mainWindow:raise()
mainWindow:focus()
end
-- otui covered, now support functions
function getPattern(category, pattern, safe)
@ -1162,10 +1190,11 @@ macro(100, function()
}
]]
for i, entry in pairs(currentSettings.attackTable) do
for i, child in ipairs(panel.entryList:getChildren()) do
local entry = child.params
local attackData = entry.itemId > 100 and entry.itemId or entry.spell
if entry.enabled and manapercent() >= entry.mana then
if (entry.spell and canCast(entry.spell, not currentSettings.ignoreMana, not currentSettings.Cooldown)) or (entry.itemId > 100 and (not currentSettings.Visible or findItem(entry.itemId))) then
if (type(attackData) == "string" and canCast(entry.spell, not currentSettings.ignoreMana, not currentSettings.Cooldown)) or (entry.itemId > 100 and (not currentSettings.Visible or findItem(entry.itemId))) then
-- first PVP scenario
if currentSettings.pvpMode and target():getHealthPercent() >= entry.minHp and target():getHealthPercent() <= entry.maxHp and target():canShoot() then
if entry.category == 2 then
@ -1193,8 +1222,10 @@ macro(100, function()
local safe = currentSettings.PvpSafe and spellPatterns[pCat][entry.pattern][2] or false
local monsterAmount = pCat ~= 8 and getMonstersInArea(entry.category, anchorParam, spellPatterns[pCat][entry.pattern][1], entry.minHp, entry.maxHp, safe, entry.monsters)
if (pattern ~= 8 and (entry.orMore and monsterAmount >= entry.count or not entry.orMore and monsterAmount == entry.count)) or (pattern == 8 and bestSide >= entry.count and (not currentSettings.PvpSafe or getPlayers(2) == 0)) then
if (not currentSettings.BlackListSafe or not isBlackListedPlayerInRange(currentSettings.AntiRsRange)) and (not currentSettings.Kills or killsToRs() > currentSettings.KillsAmount) then
return executeAttackBotAction(entry.category, attackData, entry.cooldown)
end
end
elseif entry.category == 2 then
local pCat = entry.patternCategory
local safe = currentSettings.PvpSafe and spellPatterns[pCat][entry.pattern][2] or false
@ -1206,10 +1237,12 @@ macro(100, function()
pos = data.pos
end
if monsterAmount and (entry.orMore and monsterAmount >= entry.count or not entry.orMore and monsterAmount == entry.count) then
if (not currentSettings.BlackListSafe or not isBlackListedPlayerInRange(currentSettings.AntiRsRange)) and (not currentSettings.Kills or killsToRs() > currentSettings.KillsAmount) then
return useWith(attackData, g_map.getTile(pos):getTopUseThing())
end
end
end
end
end
end
end)

View File

@ -1,6 +1,6 @@
AttackEntry < UIWidget
background-color: alpha
text-offset: 18 1
text-offset: 35 1
focusable: true
height: 16
font: verdana-11px-rounded
@ -15,6 +15,22 @@ AttackEntry < UIWidget
margin-top: 2
margin-left: 3
UIItem
id: id
anchors.left: prev.right
anchors.verticalCenter: parent.verticalCenter
size: 16 16
focusable: false
visible: false
UIWidget
id: spell
anchors.left: enabled.right
anchors.verticalCenter: parent.verticalCenter
size: 12 12
margin-left: 1
image-source: /images/game/dangerous
$focus:
background-color: #00000055
@ -537,6 +553,7 @@ AttackBotWindow < MainWindow
size: 535 300
padding: 15
text: AttackBot v2
@onEscape: self:hide()
Label
id: mainLabel

View File

@ -4,7 +4,6 @@ local panelName = "BOTserver"
local ui = setupUI([[
Panel
height: 18
Button
id: botServer
anchors.left: parent.left
@ -28,6 +27,7 @@ end
local config = storage[panelName]
if not storage.BotServerChannel then
math.randomseed(os.time())
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
end

View File

@ -77,6 +77,13 @@ Panel
conditionsWindow = UI.createWindow('ConditionsWindow', rootWidget)
conditionsWindow:hide()
conditionsWindow.onVisibilityChange = function(widget, visible)
if not visible then
vBotConfigSave("heal")
end
end
-- text edits
conditionsWindow.Cure.PoisonCost:setText(config.poisonCost)
conditionsWindow.Cure.PoisonCost.onTextChange = function(widget, text)
@ -220,7 +227,13 @@ Panel
-- buttons
conditionsWindow.closeButton.onClick = function(widget)
conditionsWindow:hide()
vBotConfigSave("heal")
end
Conditions = {}
Conditions.show = function()
conditionsWindow:show()
conditionsWindow:raise()
conditionsWindow:focus()
end
end

View File

@ -20,6 +20,7 @@ CureConditions < Panel
margin-left: 5
text: Poison
color: #ffaa00
font: verdana-11px-rounded
Label
id: label11
@ -27,6 +28,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 40
text: Mana:
font: verdana-11px-rounded
TextEdit
id: PoisonCost
@ -34,6 +36,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CurePoison
@ -48,6 +51,7 @@ CureConditions < Panel
margin-top: 10
text: Curse
color: #ffaa00
font: verdana-11px-rounded
Label
id: label22
@ -55,6 +59,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 44
text: Mana:
font: verdana-11px-rounded
TextEdit
id: CurseCost
@ -62,6 +67,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CureCurse
@ -76,6 +82,7 @@ CureConditions < Panel
margin-top: 10
text: Bleed
color: #ffaa00
font: verdana-11px-rounded
Label
id: label33
@ -83,6 +90,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 46
text: Mana:
font: verdana-11px-rounded
TextEdit
id: BleedCost
@ -90,6 +98,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CureBleed
@ -104,6 +113,7 @@ CureConditions < Panel
margin-top: 10
text: Burn
color: #ffaa00
font: verdana-11px-rounded
Label
id: label44
@ -111,6 +121,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 50
text: Mana:
font: verdana-11px-rounded
TextEdit
id: BurnCost
@ -118,6 +129,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CureBurn
@ -132,6 +144,7 @@ CureConditions < Panel
margin-top: 10
text: Electify
color: #ffaa00
font: verdana-11px-rounded
Label
id: label55
@ -139,6 +152,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 33
text: Mana:
font: verdana-11px-rounded
TextEdit
id: ElectrifyCost
@ -146,6 +160,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CureElectrify
@ -160,6 +175,7 @@ CureConditions < Panel
margin-top: 10
text: Paralyse
color: #ffaa00
font: verdana-11px-rounded
Label
id: label66
@ -167,6 +183,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 26
text: Mana:
font: verdana-11px-rounded
TextEdit
id: ParalyseCost
@ -174,6 +191,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: CureParalyse
@ -188,6 +206,7 @@ CureConditions < Panel
margin-top: 10
margin-left: 12
text: Spell:
font: verdana-11px-rounded
TextEdit
id: ParalyseSpell
@ -195,6 +214,7 @@ CureConditions < Panel
anchors.left: prev.right
margin-left: 10
width: 100
font: verdana-11px-rounded
HoldConditions < Panel
id: Hold
@ -211,6 +231,7 @@ HoldConditions < Panel
margin-left: 5
text: Haste
color: #ffaa00
font: verdana-11px-rounded
Label
id: label11
@ -218,6 +239,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 44
text: Mana:
font: verdana-11px-rounded
TextEdit
id: HasteCost
@ -225,6 +247,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: HoldHaste
@ -239,6 +262,7 @@ HoldConditions < Panel
margin-top: 10
margin-left: 12
text: Spell:
font: verdana-11px-rounded
TextEdit
id: HasteSpell
@ -246,6 +270,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 10
width: 100
font: verdana-11px-rounded
Label
id: label3
@ -254,6 +279,7 @@ HoldConditions < Panel
margin-top: 10
text: Utana Vid
color: #ffaa00
font: verdana-11px-rounded
Label
id: label33
@ -261,6 +287,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 21
text: Mana:
font: verdana-11px-rounded
TextEdit
id: UtanaCost
@ -268,6 +295,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: HoldUtana
@ -282,6 +310,7 @@ HoldConditions < Panel
margin-top: 10
text: Utamo Vita
color: #ffaa00
font: verdana-11px-rounded
Label
id: label44
@ -289,6 +318,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 12
text: Mana:
font: verdana-11px-rounded
TextEdit
id: UtamoCost
@ -296,6 +326,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: HoldUtamo
@ -310,6 +341,7 @@ HoldConditions < Panel
margin-top: 10
text: Recovery
color: #ffaa00
font: verdana-11px-rounded
Label
id: label55
@ -317,6 +349,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 20
text: Mana:
font: verdana-11px-rounded
TextEdit
id: UturaCost
@ -324,6 +357,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 3
width: 40
font: verdana-11px-rounded
CheckBox
id: HoldUtura
@ -338,6 +372,7 @@ HoldConditions < Panel
margin-top: 10
margin-left: 12
text: Spell:
font: verdana-11px-rounded
UturaComboBox
id: UturaType
@ -345,6 +380,7 @@ HoldConditions < Panel
anchors.left: prev.right
margin-left: 10
width: 100
font: verdana-11px-rounded
CheckBox
id: IgnoreInPz
@ -377,6 +413,7 @@ HoldConditions < Panel
ConditionsWindow < MainWindow
!text: tr('Condition Manager')
size: 445 280
@onEscape: self:hide()
CureConditions
id: Cure
@ -391,6 +428,7 @@ ConditionsWindow < MainWindow
text: Cure Conditions
color: #88e3dd
margin-left: 10
font: verdana-11px-rounded
HoldConditions
id: Hold
@ -405,6 +443,7 @@ ConditionsWindow < MainWindow
text: Hold Conditions
color: #88e3dd
margin-right: 100
font: verdana-11px-rounded
HorizontalSeparator
id: separator

View File

@ -3,6 +3,7 @@ local panelName = "renameContainers"
if type(storage[panelName]) ~= "table" then
storage[panelName] = {
enabled = false;
height = 170,
purse = true;
list = {
{
@ -75,9 +76,10 @@ renameContui:setId(panelName)
g_ui.loadUIFromString([[
BackpackName < Label
background-color: alpha
text-offset: 18 0
text-offset: 18 2
focusable: true
height: 16
height: 17
font: verdana-11px-rounded
CheckBox
id: enabled
@ -85,7 +87,7 @@ BackpackName < Label
anchors.verticalCenter: parent.verticalCenter
width: 15
height: 15
margin-top: 2
margin-top: 1
margin-left: 3
$focus:
@ -95,31 +97,44 @@ BackpackName < Label
id: state
!text: tr('M')
anchors.right: remove.left
margin-right: 5
anchors.verticalCenter: parent.verticalCenter
margin-right: 1
width: 15
height: 15
Button
id: remove
!text: tr('x')
!text: tr('X')
!tooltip: tr('Remove')
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
margin-right: 15
width: 15
height: 15
Button
id: openNext
!text: tr('N')
anchors.right: state.left
anchors.verticalCenter: parent.verticalCenter
margin-right: 1
width: 15
height: 15
tooltip: Open container inside with the same ID.
ContListsWindow < MainWindow
!text: tr('Container Names')
size: 445 170
size: 465 170
@onEscape: self:hide()
TextList
id: itemList
anchors.left: parent.left
anchors.top: parent.top
size: 180 83
anchors.bottom: separator.top
width: 200
margin-bottom: 6
margin-top: 3
margin-bottom: 3
margin-left: 3
vertical-scrollbar: itemListScrollBar
@ -148,12 +163,14 @@ ContListsWindow < MainWindow
text: Name:
margin-left: 10
margin-top: 3
font: verdana-11px-rounded
TextEdit
id: contName
anchors.left: lblName.right
anchors.top: sep.top
anchors.right: parent.right
font: verdana-11px-rounded
Label
id: lblCont
@ -161,6 +178,7 @@ ContListsWindow < MainWindow
anchors.verticalCenter: contId.verticalCenter
width: 70
text: Container:
font: verdana-11px-rounded
BotItem
id: contId
@ -173,14 +191,16 @@ ContListsWindow < MainWindow
anchors.left: prev.left
anchors.right: parent.right
anchors.top: prev.bottom
anchors.bottom: separator.top
margin-bottom: 6
margin-top: 3
height: 32
Label
anchors.left: lblCont.left
anchors.verticalCenter: prev.verticalCenter
anchors.verticalCenter: sortList.verticalCenter
width: 70
text: Items:
font: verdana-11px-rounded
Button
id: addItem
@ -208,6 +228,7 @@ ContListsWindow < MainWindow
height: 15
margin-top: 2
margin-left: 3
font: verdana-11px-rounded
CheckBox
id: sort
@ -219,6 +240,7 @@ ContListsWindow < MainWindow
height: 15
margin-top: 2
margin-left: 15
font: verdana-11px-rounded
CheckBox
id: forceOpen
@ -230,6 +252,19 @@ ContListsWindow < MainWindow
height: 15
margin-top: 2
margin-left: 15
font: verdana-11px-rounded
CheckBox
id: lootBag
anchors.left: prev.right
anchors.bottom: parent.bottom
text: Loot Bag
tooltip: Open Loot Bag (gunzodus franchaise)
width: 85
height: 15
margin-top: 2
margin-left: 15
font: verdana-11px-rounded
Button
id: closeButton
@ -239,6 +274,16 @@ ContListsWindow < MainWindow
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
ResizeBorder
id: bottomResizeBorder
anchors.fill: separator
height: 3
minimum: 170
maximum: 245
margin-left: 3
margin-right: 3
background: #ffffff88
]])
function findItemsInArray(t, tfind)
@ -308,7 +353,6 @@ function reopenBackpacks()
end
end)
end
rootWidget = g_ui.getRootWidget()
@ -316,6 +360,14 @@ if rootWidget then
contListWindow = UI.createWindow('ContListsWindow', rootWidget)
contListWindow:hide()
contListWindow.onGeometryChange = function(widget, old, new)
if old.height == 0 then return end
config.height = new.height
end
contListWindow:setHeight(config.height or 170)
renameContui.editContList.onClick = function(widget)
contListWindow:show()
contListWindow:raise()
@ -354,6 +406,12 @@ if rootWidget then
end
contListWindow.forceOpen:setChecked(config.forceOpen)
contListWindow.lootBag.onClick = function(widget)
config.lootBag = not config.lootBag
contListWindow.lootBag:setChecked(config.lootBag)
end
contListWindow.lootBag:setChecked(config.lootBag)
local function refreshSortList(k, t)
t = t or {}
UI.Container(function()
@ -398,13 +456,18 @@ if rootWidget then
label.state:setColor(entry.min and '#00FF00' or '#FF0000')
label.state:setTooltip(entry.min and 'Open Minimised' or 'Do not minimise')
end
label.openNext.onClick = function(widget)
entry.openNext = not entry.openNext
label.openNext:setChecked(entry.openNext)
label.openNext:setColor(entry.openNext and '#00FF00' or '#FF0000')
end
label:setText(entry.value)
label.enabled:setChecked(entry.enabled)
label.enabled:setTooltip(entry.enabled and 'Disable' or 'Enable')
label.enabled:setImageColor(entry.enabled and '#00FF00' or '#FF0000')
label.state:setColor(entry.min and '#00FF00' or '#FF0000')
label.state:setTooltip(entry.min and 'Open Minimised' or 'Do not minimise')
label.openNext:setColor(entry.openNext and '#00FF00' or '#FF0000')
if tFocus and entry.item == tFocus then
tFocus = label
@ -440,12 +503,12 @@ if rootWidget then
end
onContainerOpen(function(container, previousContainer)
if renameContui.title:isOn() then
if not container.window then return end
local containerWindow = container.window
if not previousContainer then
containerWindow:setContentHeight(34)
end
local storageVal = config.list
if storageVal and #storageVal > 0 then
for _, entry in pairs(storageVal) do
@ -453,13 +516,43 @@ onContainerOpen(function(container, previousContainer)
if entry.min then
containerWindow:minimize()
end
if renameContui.title:isOn() then
containerWindow:setText(entry.value)
end
if entry.openNext then
for i, item in ipairs(container:getItems()) do
if item:getId() == entry.item then
local time = #storageVal * 250
schedule(time, function()
time = time + 250
g_game.open(item)
end)
end
end
end
end
end
end
end)
local function nameContainersOnLogin()
for i, container in ipairs(getContainers()) do
if renameContui.title:isOn() then
if not container.window then return end
local containerWindow = container.window
local storageVal = config.list
if storageVal and #storageVal > 0 then
for _, entry in pairs(storageVal) do
if entry.enabled and string.find(container:getContainerItem():getId(), entry.item) then
containerWindow:setText(entry.value)
end
end
end
end
end
end
nameContainersOnLogin()
local function moveItem(item, destination)
return g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), item:getCount())
end
@ -522,5 +615,12 @@ macro(500, function()
if config.purse and config.forceOpen and not getContainerByItem(23396) then
return use(getPurse())
end
if config.lootBag and config.forceOpen and not getContainerByItem(23721) then
if findItem(23721) then
g_game.open(findItem(23721), getContainerByItem(23396))
else
return use(getPurse())
end
end
delay(1500)
end)

View File

@ -50,7 +50,8 @@ local conditions = { -- always add new conditions at the bottom
"Player is paralyzed", -- nothing 10
"Player is in protection zone", -- nothing 11
"Players around is more than:", -- spinbox 12
"Players around is less than:" -- spinbox 13
"Players around is less than:", -- spinbox 13
"TargetBot Danger is Above:" -- spinbox 14
}
local conditionNumber = 1
@ -225,25 +226,33 @@ inputPanel.optionalCondition.pre.onClick = function()
setCondition(false, optionalConditionNumber)
end
listPanel.up.onClick = function()
local n = listPanel.list:getChildIndex(listPanel.list:getFocusedChild())
listPanel.up.onClick = function(widget)
local focused = listPanel.list:getFocusedChild()
local n = listPanel.list:getChildIndex(focused)
local t = config.rules
t[n], t[n-1] = t[n-1], t[n]
listPanel.up:setEnabled(false)
listPanel.down:setEnabled(false)
refreshRules()
if n-1 == 1 then
widget:setEnabled(false)
end
listPanel.down:setEnabled(true)
listPanel.list:moveChildToIndex(focused, n-1)
listPanel.list:ensureChildVisible(focused)
end
listPanel.down.onClick = function()
local n = listPanel.list:getChildIndex(listPanel.list:getFocusedChild())
listPanel.down.onClick = function(widget)
local focused = listPanel.list:getFocusedChild()
local n = listPanel.list:getChildIndex(focused)
local t = config.rules
t[n], t[n+1] = t[n+1], t[n]
listPanel.up:setEnabled(false)
listPanel.down:setEnabled(false)
refreshRules()
end
if n + 1 == listPanel.list:getChildCount() then
widget:setEnabled(false)
end
listPanel.up:setEnabled(true)
listPanel.list:moveChildToIndex(focused, n+1)
listPanel.list:ensureChildVisible(focused)
end
function getItemsFromBox()
local t = {}
@ -262,6 +271,19 @@ function refreshItemBox(reset)
local box = inputPanel.itemBox
local childAmount = box:getChildCount()
--height
if #getItemsFromBox() < 7 then
mainWindow:setHeight(345)
inputPanel:setHeight(265)
listPanel:setHeight(265)
box:setHeight(40)
else
mainWindow:setHeight(370)
inputPanel:setHeight(300)
listPanel:setHeight(300)
box:setHeight(80)
end
if reset then
box:destroyChildren()
local widget = UI.createWidget("BotItem", box)
@ -285,9 +307,8 @@ function refreshItemBox(reset)
widget:destroy()
end
refreshItemBox()
refreshItemBox()
end
elseif box:getLastChild():getItemId() > 100 and childAmount < max then
elseif box:getLastChild():getItemId() > 100 and childAmount <= max then
local widget = UI.createWidget("BotItem", box)
widget.onItemChange = function(widget)
local id = widget:getItemId()
@ -296,7 +317,6 @@ function refreshItemBox(reset)
widget:destroy()
end
refreshItemBox()
refreshItemBox()
end
end
end
@ -324,6 +344,7 @@ function refreshRules()
list:destroyChildren()
for i,v in pairs(config.rules) do
local widget = UI.createWidget('Rule', list)
widget:setId(v.name)
widget:setText(v.name)
widget.remove.onClick = function()
widget:destroy()
@ -513,30 +534,33 @@ end
--"Player is paralyzed", -- nothing 10
local pressedKey = ""
local lastPress = now
onKeyPress(function(keys)
pressedKey = keys
lastPress = now
schedule(100, function()
if now - lastPress > 20 then
pressedKey = ""
end
end)
end)
local function interpreteCondition(n, v)
local hp = hppercent()
local mp = manapercent()
local mobs = getMonsters()
local players = getPlayers()
if n == 1 then
return true
elseif n == 2 then
return mobs > v
return getMonsters() > v
elseif n == 3 then
return mobs < v
return getMonsters() < v
elseif n == 4 then
return hp < v
return hppercent() < v
elseif n == 5 then
return hp > v
return hppercent() > v
elseif n == 6 then
return mp < v
return manapercent() < v
elseif n == 7 then
return mp > v
return manapercent() > v
elseif n == 8 then
return target() and target():getName():lower() == v:lower() or false
elseif n == 9 then
@ -546,10 +570,13 @@ local function interpreteCondition(n, v)
elseif n == 11 then
return isInPz()
elseif n == 12 then
return players > v
return getPlayers() > v
elseif n == 13 then
return players < v
return getPlayers() < v
elseif n == 14 then
return TargetBot.Danger() > v and TargetBot.isOn()
end
end
local function finalCheck(first,relation,second)
@ -605,7 +632,16 @@ EquipManager = macro(50, function()
if #config.rules == 0 then return end
for i, rule in ipairs(config.rules) do
local widget = listPanel.list:getChildById(rule.name)
if mainWindow:isVisible() then
for i, child in ipairs(listPanel.list:getChildren()) do
if child ~= widget then
child:setColor('white')
end
end
end
if rule.enabled then
widget:setColor('green')
local firstCondition = interpreteCondition(rule.mainCondition, rule.mainValue)
local optionalCondition = nil
if rule.relation ~= "-" then

View File

@ -1,8 +1,11 @@
local standBySpells = false
local standByItems = false
local red = "#ff0800" -- "#ff0800" / #ea3c53 best
local blue = "#7ef9ff"
setDefaultTab("HP")
healPanelName = "healbot"
local healPanelName = "healbot"
local ui = setupUI([[
Panel
height: 38
@ -168,9 +171,9 @@ activeProfileColor()
ui.title:setOn(currentSettings.enabled)
ui.title.onClick = function(widget)
currentSettings.enabled = not currentSettings.enabled
widget:setOn(currentSettings.enabled)
vBotConfigSave("heal")
currentSettings.enabled = not currentSettings.enabled
widget:setOn(currentSettings.enabled)
vBotConfigSave("heal")
end
ui.settings.onClick = function(widget)
@ -184,45 +187,64 @@ if rootWidget then
healWindow = UI.createWindow('HealWindow', rootWidget)
healWindow:hide()
healWindow.onVisibilityChange = function(widget, visible)
if not visible then
vBotConfigSave("heal")
healWindow.healer:show()
healWindow.settings:hide()
healWindow.settingsButton:setText("Settings")
end
end
healWindow.settingsButton.onClick = function(widget)
if healWindow.healer:isVisible() then
healWindow.healer:hide()
healWindow.settings:show()
widget:setText("Back")
else
healWindow.healer:show()
healWindow.settings:hide()
widget:setText("Settings")
end
end
local setProfileName = function()
ui.name:setText(currentSettings.name)
end
healWindow.Name.onTextChange = function(widget, text)
healWindow.settings.profiles.Name.onTextChange = function(widget, text)
currentSettings.name = text
setProfileName()
end
healWindow.Visible.onClick = function(widget)
healWindow.settings.list.Visible.onClick = function(widget)
currentSettings.Visible = not currentSettings.Visible
healWindow.Visible:setChecked(currentSettings.Visible)
healWindow.settings.list.Visible:setChecked(currentSettings.Visible)
end
healWindow.Cooldown.onClick = function(widget)
healWindow.settings.list.Cooldown.onClick = function(widget)
currentSettings.Cooldown = not currentSettings.Cooldown
healWindow.Cooldown:setChecked(currentSettings.Cooldown)
healWindow.settings.list.Cooldown:setChecked(currentSettings.Cooldown)
end
healWindow.Interval.onClick = function(widget)
healWindow.settings.list.Interval.onClick = function(widget)
currentSettings.Interval = not currentSettings.Interval
healWindow.Interval:setChecked(currentSettings.Interval)
healWindow.settings.list.Interval:setChecked(currentSettings.Interval)
end
healWindow.Conditions.onClick = function(widget)
healWindow.settings.list.Conditions.onClick = function(widget)
currentSettings.Conditions = not currentSettings.Conditions
healWindow.Conditions:setChecked(currentSettings.Conditions)
healWindow.settings.list.Conditions:setChecked(currentSettings.Conditions)
end
healWindow.Delay.onClick = function(widget)
healWindow.settings.list.Delay.onClick = function(widget)
currentSettings.Delay = not currentSettings.Delay
healWindow.Delay:setChecked(currentSettings.Delay)
healWindow.settings.list.Delay:setChecked(currentSettings.Delay)
end
healWindow.MessageDelay.onClick = function(widget)
healWindow.settings.list.MessageDelay.onClick = function(widget)
currentSettings.MessageDelay = not currentSettings.MessageDelay
healWindow.MessageDelay:setChecked(currentSettings.MessageDelay)
healWindow.settings.list.MessageDelay:setChecked(currentSettings.MessageDelay)
end
local refreshSpells = function()
if currentSettings.spellTable then
for i, child in pairs(healWindow.spells.spellList:getChildren()) do
child:destroy()
end
healWindow.healer.spells.spellList:destroyChildren()
for _, entry in pairs(currentSettings.spellTable) do
local label = UI.createWidget("SpellEntry", healWindow.spells.spellList)
local label = UI.createWidget("SpellEntry", healWindow.healer.spells.spellList)
label.enabled:setChecked(entry.enabled)
label.enabled.onClick = function(widget)
standBySpells = false
@ -237,7 +259,7 @@ if rootWidget then
reindexTable(currentSettings.spellTable)
label:destroy()
end
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ":" .. entry.spell)
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ": " .. entry.spell)
end
end
end
@ -245,11 +267,9 @@ if rootWidget then
local refreshItems = function()
if currentSettings.itemTable then
for i, child in pairs(healWindow.items.itemList:getChildren()) do
child:destroy()
end
healWindow.healer.items.itemList:destroyChildren()
for _, entry in pairs(currentSettings.itemTable) do
local label = UI.createWidget("SpellEntry", healWindow.items.itemList)
local label = UI.createWidget("ItemEntry", healWindow.healer.items.itemList)
label.enabled:setChecked(entry.enabled)
label.enabled.onClick = function(widget)
standBySpells = false
@ -264,138 +284,87 @@ if rootWidget then
reindexTable(currentSettings.itemTable)
label:destroy()
end
label:setText(entry.origin .. entry.sign .. entry.value .. ":" .. entry.item)
label.id:setItemId(entry.item)
label:setText(entry.origin .. entry.sign .. entry.value .. ": " .. entry.item)
end
end
end
refreshItems()
healWindow.spells.MoveUp.onClick = function(widget)
local input = healWindow.spells.spellList:getFocusedChild()
healWindow.healer.spells.MoveUp.onClick = function(widget)
local input = healWindow.healer.spells.spellList:getFocusedChild()
if not input then return end
local index = healWindow.spells.spellList:getChildIndex(input)
local index = healWindow.healer.spells.spellList:getChildIndex(input)
if index < 2 then return end
local move
if currentSettings.spellTable and #currentSettings.spellTable > 0 then
for _, entry in pairs(currentSettings.spellTable) do
if entry.index == index -1 then
move = entry
end
if entry.index == index then
move.index = index
entry.index = index -1
end
end
end
table.sort(currentSettings.spellTable, function(a,b) return a.index < b.index end)
local t = currentSettings.spellTable
healWindow.spells.spellList:moveChildToIndex(input, index - 1)
healWindow.spells.spellList:ensureChildVisible(input)
t[index],t[index-1] = t[index-1], t[index]
healWindow.healer.spells.spellList:moveChildToIndex(input, index - 1)
healWindow.healer.spells.spellList:ensureChildVisible(input)
end
healWindow.spells.MoveDown.onClick = function(widget)
local input = healWindow.spells.spellList:getFocusedChild()
healWindow.healer.spells.MoveDown.onClick = function(widget)
local input = healWindow.healer.spells.spellList:getFocusedChild()
if not input then return end
local index = healWindow.spells.spellList:getChildIndex(input)
if index >= healWindow.spells.spellList:getChildCount() then return end
local index = healWindow.healer.spells.spellList:getChildIndex(input)
if index >= healWindow.healer.spells.spellList:getChildCount() then return end
local move
local move2
if currentSettings.spellTable and #currentSettings.spellTable > 0 then
for _, entry in pairs(currentSettings.spellTable) do
if entry.index == index +1 then
move = entry
end
if entry.index == index then
move2 = entry
end
end
if move and move2 then
move.index = index
move2.index = index + 1
end
end
table.sort(currentSettings.spellTable, function(a,b) return a.index < b.index end)
local t = currentSettings.spellTable
healWindow.spells.spellList:moveChildToIndex(input, index + 1)
healWindow.spells.spellList:ensureChildVisible(input)
t[index],t[index+1] = t[index+1],t[index]
healWindow.healer.spells.spellList:moveChildToIndex(input, index + 1)
healWindow.healer.spells.spellList:ensureChildVisible(input)
end
healWindow.items.MoveUp.onClick = function(widget)
local input = healWindow.items.itemList:getFocusedChild()
healWindow.healer.items.MoveUp.onClick = function(widget)
local input = healWindow.healer.items.itemList:getFocusedChild()
if not input then return end
local index = healWindow.items.itemList:getChildIndex(input)
local index = healWindow.healer.items.itemList:getChildIndex(input)
if index < 2 then return end
local move
if currentSettings.itemTable and #currentSettings.itemTable > 0 then
for _, entry in pairs(currentSettings.itemTable) do
if entry.index == index -1 then
move = entry
end
if entry.index == index then
move.index = index
entry.index = index - 1
end
end
end
table.sort(currentSettings.itemTable, function(a,b) return a.index < b.index end)
local t = currentSettings.itemTable
healWindow.items.itemList:moveChildToIndex(input, index - 1)
healWindow.items.itemList:ensureChildVisible(input)
t[index],t[index-1] = t[index-1], t[index]
healWindow.healer.items.itemList:moveChildToIndex(input, index - 1)
healWindow.healer.items.itemList:ensureChildVisible(input)
end
healWindow.items.MoveDown.onClick = function(widget)
local input = healWindow.items.itemList:getFocusedChild()
healWindow.healer.items.MoveDown.onClick = function(widget)
local input = healWindow.healer.items.itemList:getFocusedChild()
if not input then return end
local index = healWindow.items.itemList:getChildIndex(input)
if index >= healWindow.items.itemList:getChildCount() then return end
local index = healWindow.healer.items.itemList:getChildIndex(input)
if index >= healWindow.healer.items.itemList:getChildCount() then return end
local move
local move2
if currentSettings.itemTable and #currentSettings.itemTable > 0 then
for _, entry in pairs(currentSettings.itemTable) do
if entry.index == index +1 then
move = entry
end
if entry.index == index then
move2 = entry
end
end
if move and move2 then
move.index = index
move2.index = index + 1
end
end
table.sort(currentSettings.itemTable, function(a,b) return a.index < b.index end)
local t = currentSettings.itemTable
healWindow.items.itemList:moveChildToIndex(input, index + 1)
healWindow.items.itemList:ensureChildVisible(input)
t[index],t[index+1] = t[index+1],t[index]
healWindow.healer.items.itemList:moveChildToIndex(input, index + 1)
healWindow.healer.items.itemList:ensureChildVisible(input)
end
healWindow.spells.addSpell.onClick = function(widget)
healWindow.healer.spells.addSpell.onClick = function(widget)
local spellFormula = healWindow.spells.spellFormula:getText():trim()
local manaCost = tonumber(healWindow.spells.manaCost:getText())
local spellTrigger = tonumber(healWindow.spells.spellValue:getText())
local spellSource = healWindow.spells.spellSource:getCurrentOption().text
local spellEquasion = healWindow.spells.spellCondition:getCurrentOption().text
local spellFormula = healWindow.healer.spells.spellFormula:getText():trim()
local manaCost = tonumber(healWindow.healer.spells.manaCost:getText())
local spellTrigger = tonumber(healWindow.healer.spells.spellValue:getText())
local spellSource = healWindow.healer.spells.spellSource:getCurrentOption().text
local spellEquasion = healWindow.healer.spells.spellCondition:getCurrentOption().text
local source
local equasion
if not manaCost then
warn("HealBot: incorrect mana cost value!")
healWindow.spells.spellFormula:setText('')
healWindow.spells.spellValue:setText('')
healWindow.spells.manaCost:setText('')
healWindow.healer.spells.spellFormula:setText('')
healWindow.healer.spells.spellValue:setText('')
healWindow.healer.spells.manaCost:setText('')
return
end
if not spellTrigger then
warn("HealBot: incorrect condition value!")
healWindow.spells.spellFormula:setText('')
healWindow.spells.spellValue:setText('')
healWindow.spells.manaCost:setText('')
healWindow.healer.spells.spellFormula:setText('')
healWindow.healer.spells.spellValue:setText('')
healWindow.healer.spells.manaCost:setText('')
return
end
@ -421,28 +390,28 @@ if rootWidget then
if spellFormula:len() > 0 then
table.insert(currentSettings.spellTable, {index = #currentSettings.spellTable+1, spell = spellFormula, sign = equasion, origin = source, cost = manaCost, value = spellTrigger, enabled = true})
healWindow.spells.spellFormula:setText('')
healWindow.spells.spellValue:setText('')
healWindow.spells.manaCost:setText('')
healWindow.healer.spells.spellFormula:setText('')
healWindow.healer.spells.spellValue:setText('')
healWindow.healer.spells.manaCost:setText('')
end
standBySpells = false
standByItems = false
refreshSpells()
end
healWindow.items.addItem.onClick = function(widget)
healWindow.healer.items.addItem.onClick = function(widget)
local id = healWindow.items.itemId:getItemId()
local trigger = tonumber(healWindow.items.itemValue:getText())
local src = healWindow.items.itemSource:getCurrentOption().text
local eq = healWindow.items.itemCondition:getCurrentOption().text
local id = healWindow.healer.items.itemId:getItemId()
local trigger = tonumber(healWindow.healer.items.itemValue:getText())
local src = healWindow.healer.items.itemSource:getCurrentOption().text
local eq = healWindow.healer.items.itemCondition:getCurrentOption().text
local source
local equasion
if not trigger then
warn("HealBot: incorrect trigger value!")
healWindow.items.itemId:setItemId(0)
healWindow.items.itemValue:setText('')
healWindow.healer.items.itemId:setItemId(0)
healWindow.healer.items.itemValue:setText('')
return
end
@ -471,28 +440,27 @@ if rootWidget then
standBySpells = false
standByItems = false
refreshItems()
healWindow.items.itemId:setItemId(0)
healWindow.items.itemValue:setText('')
healWindow.healer.items.itemId:setItemId(0)
healWindow.healer.items.itemValue:setText('')
end
end
healWindow.closeButton.onClick = function(widget)
healWindow:hide()
vBotConfigSave("heal")
end
local loadSettings = function()
ui.title:setOn(currentSettings.enabled)
setProfileName()
healWindow.Name:setText(currentSettings.name)
healWindow.settings.profiles.Name:setText(currentSettings.name)
refreshSpells()
refreshItems()
healWindow.Visible:setChecked(currentSettings.Visible)
healWindow.Cooldown:setChecked(currentSettings.Cooldown)
healWindow.Delay:setChecked(currentSettings.Delay)
healWindow.MessageDelay:setChecked(currentSettings.MessageDelay)
healWindow.Interval:setChecked(currentSettings.Interval)
healWindow.Conditions:setChecked(currentSettings.Conditions)
healWindow.settings.list.Visible:setChecked(currentSettings.Visible)
healWindow.settings.list.Cooldown:setChecked(currentSettings.Cooldown)
healWindow.settings.list.Delay:setChecked(currentSettings.Delay)
healWindow.settings.list.MessageDelay:setChecked(currentSettings.MessageDelay)
healWindow.settings.list.Interval:setChecked(currentSettings.Interval)
healWindow.settings.list.Conditions:setChecked(currentSettings.Conditions)
end
loadSettings()
@ -525,7 +493,7 @@ if rootWidget then
end
end
healWindow.ResetSettings.onClick = function()
healWindow.settings.profiles.ResetSettings.onClick = function()
resetSettings()
loadSettings()
end
@ -566,15 +534,23 @@ if rootWidget then
profileChange()
end
end
HealBot.show = function()
healWindow:show()
healWindow:raise()
healWindow:focus()
end
end
-- spells
macro(100, function()
if standBySpells then return end
if not currentSettings.enabled or modules.game_cooldown.isGroupCooldownIconActive(2) or #currentSettings.spellTable == 0 then return end
if not currentSettings.enabled then return end
local somethingIsOnCooldown = false
for _, entry in pairs(currentSettings.spellTable) do
if canCast(entry.spell, not currentSettings.Conditions, not currentSettings.Cooldown) and entry.enabled and entry.cost < mana() then
if entry.enabled and entry.cost < mana() then
if canCast(entry.spell, not currentSettings.Conditions, not currentSettings.Cooldown) then
if entry.origin == "HP%" then
if entry.sign == "=" and hppercent() == entry.value then
say(entry.spell)
@ -631,9 +607,14 @@ macro(100, function()
return
end
end
else
somethingIsOnCooldown = true
end
end
end
if not somethingIsOnCooldown then
standBySpells = true
end
end)
-- items

View File

@ -1,3 +1,9 @@
SettingCheckBox < CheckBox
text-wrap: true
text-auto-resize: true
margin-top: 3
font: verdana-11px-rounded
SpellSourceBoxPopupMenu < ComboBoxPopupMenu
SpellSourceBoxPopupMenuButton < ComboBoxPopupMenuButton
SpellSourceBox < ComboBox
@ -18,9 +24,10 @@ SpellConditionBox < ComboBox
SpellEntry < Label
background-color: alpha
text-offset: 18 0
text-offset: 18 1
focusable: true
height: 16
font: verdana-11px-rounded
CheckBox
id: enabled
@ -39,14 +46,33 @@ SpellEntry < Label
!text: tr('x')
anchors.right: parent.right
margin-right: 15
text-offset: 1 0
width: 15
height: 15
ItemEntry < Label
background-color: alpha
text-offset: 2 0
text-offset: 40 1
focusable: true
height: 16
font: verdana-11px-rounded
CheckBox
id: enabled
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 15
height: 15
margin-top: 2
margin-left: 3
UIItem
id: id
anchors.left: prev.right
margin-left: 3
anchors.verticalCenter: parent.verticalCenter
size: 15 15
focusable: false
$focus:
background-color: #00000055
@ -56,30 +82,37 @@ ItemEntry < Label
!text: tr('x')
anchors.right: parent.right
margin-right: 15
text-offset: 1 0
width: 15
height: 15
SpellHealing < Panel
image-source: /images/ui/panel_flat
image-border: 6
padding: 3
SpellHealing < FlatPanel
size: 490 130
Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
margin-left: 5
text: Spell Healing
color: #269e26
font: verdana-11px-rounded
SpellSourceBox
id: spellSource
anchors.top: spellList.top
anchors.left: spellList.right
margin-left: 80
width: 125
font: verdana-11px-rounded
Label
id: whenSpell
anchors.left: spellList.right
anchors.top: parent.top
anchors.verticalCenter: prev.verticalCenter
text: When
margin-top: 10
margin-left: 7
SpellSourceBox
id: spellSource
anchors.top: parent.top
anchors.left: whenSpell.right
margin-top: 5
margin-left: 35
width: 128
font: verdana-11px-rounded
Label
id: isSpell
@ -88,6 +121,7 @@ SpellHealing < Panel
text: Is
margin-top: 9
margin-left: 7
font: verdana-11px-rounded
SpellConditionBox
id: spellCondition
@ -95,13 +129,15 @@ SpellHealing < Panel
anchors.top: spellSource.bottom
marin-top: 15
width: 80
font: verdana-11px-rounded
TextEdit
id: spellValue
anchors.left: spellCondition.right
anchors.top: spellCondition.top
anchors.bottom: spellCondition.bottom
width: 49
anchors.right: spellSource.right
font: verdana-11px-rounded
Label
id: castSpell
@ -109,12 +145,14 @@ SpellHealing < Panel
anchors.top: isSpell.bottom
text: Cast
margin-top: 9
font: verdana-11px-rounded
TextEdit
id: spellFormula
anchors.left: spellCondition.left
anchors.top: spellCondition.bottom
anchors.right: spellValue.right
font: verdana-11px-rounded
Label
id: manaSpell
@ -122,21 +160,26 @@ SpellHealing < Panel
anchors.top: castSpell.bottom
text: Mana Cost:
margin-top: 8
font: verdana-11px-rounded
TextEdit
id: manaCost
anchors.left: spellFormula.left
anchors.top: spellFormula.bottom
width: 40
font: verdana-11px-rounded
TextList
id: spellList
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
padding: 1
size: 270 116
margin-bottom: 3
margin-left: 3
padding-top: 2
width: 270
margin-bottom: 7
margin-left: 7
margin-top: 10
vertical-scrollbar: spellListScrollBar
VerticalScrollBar
@ -150,9 +193,7 @@ SpellHealing < Panel
Button
id: addSpell
anchors.right: spellFormula.right
anchors.bottom: parent.bottom
margin-bottom: 2
margin-right: 10
anchors.bottom: spellList.bottom
text: Add
size: 40 17
font: cipsoftFont
@ -160,8 +201,7 @@ SpellHealing < Panel
Button
id: MoveUp
anchors.right: prev.left
anchors.bottom: parent.bottom
margin-bottom: 2
anchors.bottom: prev.bottom
margin-right: 5
text: Move Up
size: 55 17
@ -170,34 +210,39 @@ SpellHealing < Panel
Button
id: MoveDown
anchors.right: prev.left
anchors.bottom: parent.bottom
margin-bottom: 2
anchors.bottom: prev.bottom
margin-right: 5
text: Move Down
size: 55 17
font: cipsoftFont
ItemHealing < Panel
image-source: /images/ui/panel_flat
image-border: 6
padding: 3
size: 490 130
ItemHealing < FlatPanel
size: 490 120
Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
margin-left: 5
text: Item Healing
color: #ff4513
font: verdana-11px-rounded
SpellSourceBox
id: itemSource
anchors.top: itemList.top
anchors.right: parent.right
margin-right: 10
width: 128
font: verdana-11px-rounded
Label
id: whenItem
anchors.left: itemList.right
anchors.top: parent.top
anchors.verticalCenter: prev.verticalCenter
text: When
margin-top: 10
margin-left: 7
SpellSourceBox
id: itemSource
anchors.top: parent.top
anchors.left: whenItem.right
margin-top: 5
margin-left: 35
width: 128
font: verdana-11px-rounded
Label
id: isItem
@ -206,6 +251,7 @@ ItemHealing < Panel
text: Is
margin-top: 9
margin-left: 7
font: verdana-11px-rounded
SpellConditionBox
id: itemCondition
@ -213,6 +259,7 @@ ItemHealing < Panel
anchors.top: itemSource.bottom
marin-top: 15
width: 80
font: verdana-11px-rounded
TextEdit
id: itemValue
@ -220,6 +267,7 @@ ItemHealing < Panel
anchors.top: itemCondition.top
anchors.bottom: itemCondition.bottom
width: 49
font: verdana-11px-rounded
Label
id: useItem
@ -227,6 +275,7 @@ ItemHealing < Panel
anchors.top: isItem.bottom
text: Use
margin-top: 15
font: verdana-11px-rounded
BotItem
id: itemId
@ -237,11 +286,13 @@ ItemHealing < Panel
id: itemList
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
padding: 1
size: 270 116
margin-top: 3
margin-bottom: 3
margin-left: 3
padding-top: 2
width: 270
margin-top: 10
margin-bottom: 7
margin-left: 8
vertical-scrollbar: itemListScrollBar
VerticalScrollBar
@ -255,9 +306,7 @@ ItemHealing < Panel
Button
id: addItem
anchors.right: itemValue.right
anchors.bottom: parent.bottom
margin-bottom: 2
margin-right: 10
anchors.bottom: itemList.bottom
text: Add
size: 40 17
font: cipsoftFont
@ -265,8 +314,7 @@ ItemHealing < Panel
Button
id: MoveUp
anchors.right: prev.left
anchors.bottom: parent.bottom
margin-bottom: 2
anchors.bottom: prev.bottom
margin-right: 5
text: Move Up
size: 55 17
@ -275,20 +323,19 @@ ItemHealing < Panel
Button
id: MoveDown
anchors.right: prev.left
anchors.bottom: parent.bottom
margin-bottom: 2
anchors.bottom: prev.bottom
margin-right: 5
text: Move Down
size: 55 17
font: cipsoftFont
HealWindow < MainWindow
!text: tr('Self Healer')
size: 800 350
HealerPanel < Panel
size: 510 275
SpellHealing
id: spells
anchors.top: parent.top
margin-top: 8
anchors.left: parent.left
ItemHealing
@ -297,95 +344,128 @@ HealWindow < MainWindow
anchors.left: parent.left
margin-top: 10
VerticalSeparator
id: sep
anchors.top: parent.top
anchors.left: prev.right
anchors.bottom: separator.top
margin-left: 10
margin-bottom: 5
HealBotSettingsPanel < Panel
size: 500 267
padding-top: 8
FlatPanel
id: list
anchors.fill: parent
margin-right: 240
padding-left: 6
padding-right: 6
padding-top: 6
layout:
type: verticalBox
Label
anchors.left: prev.right
anchors.right: parent.right
anchors.top: parent.top
text: Additional Settings
text-align: center
text: Additional Options
font: verdana-11px-rounded
HorizontalSeparator
anchors.left: prev.left
anchors.top: prev.bottom
anchors.right: prev.right
margin-top: 5
margin-left: 10
CheckBox
SettingCheckBox
id: Cooldown
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 10
margin-left: 5
width: 200
text: Check spell cooldowns
margin-top: 10
CheckBox
SettingCheckBox
id: Visible
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 250
text: Items must be visible (recommended)
CheckBox
SettingCheckBox
id: Delay
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 250
text: Don't use items when interacting
CheckBox
SettingCheckBox
id: Interval
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 250
text: Additional delay when looting corpses
CheckBox
SettingCheckBox
id: Conditions
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 250
text: Also check conditions from RL Tibia
CheckBox
SettingCheckBox
id: MessageDelay
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 8
width: 250
text: Cooldown based on "Aaaah..." message
VerticalSeparator
anchors.top: prev.top
anchors.bottom: prev.bottom
anchors.left: prev.right
margin-left: 8
FlatPanel
id: profiles
anchors.fill: parent
anchors.left: prev.left
margin-left: 8
margin-right: 8
padding: 8
Label
anchors.left: Visible.left
anchors.bottom: separator.top
margin-bottom: 8
text: Profile:
text: Profile Settings
text-align: center
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
font: verdana-11px-rounded
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
Label
anchors.top: prev.bottom
margin-top: 30
anchors.left: parent.left
anchors.right: parent.right
text-align: center
font: verdana-11px-rounded
text: Profile Name:
TextEdit
id: Name
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 5
anchors.top: prev.bottom
margin-top: 3
anchors.left: parent.left
anchors.right: parent.right
Button
id: ResetSettings
anchors.verticalCenter: prev.verticalCenter
anchors.right: parent.right
text: Reset Settings
margin-top: 1
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: Reset Current Profile
text-auto-resize: true
color: #ff4513
HealWindow < MainWindow
!text: tr('Self Healer')
size: 520 360
@onEscape: self:hide()
Label
id: title
anchors.left: parent.left
anchors.top: parent.top
margin-left: 2
!text: tr('More important methods come first (Example: Exura gran above Exura)')
text-align: left
font: verdana-11px-rounded
color: #aeaeae
HealerPanel
id: healer
anchors.top: prev.bottom
anchors.left: parent.left
HealBotSettingsPanel
id: settings
anchors.top: title.bottom
anchors.left: parent.left
visible: false
HorizontalSeparator
id: separator
@ -401,5 +481,12 @@ HealWindow < MainWindow
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
margin-right: 5
Button
id: settingsButton
!text: tr('Settings')
font: cipsoftFont
anchors.left: parent.left
anchors.bottom: parent.bottom
size: 45 21

View File

@ -11,10 +11,54 @@
br, Vithrax
]]
local lootWorth = 0
local wasteWorth = 0
local balance = 0
local balanceDesc = ""
local hourDesc = ""
local desc = ""
local hour = ""
local launchTime = now
local startExp = exp()
local dmgTable = {}
local healTable = {}
local expTable = {}
local totalDmg = 0
local totalHeal = 0
local dmgDistribution = {}
local first = {l="-", r="0"}
local second = {l="-", r="0"}
local third = {l="-", r="0"}
local fourth = {l="-", r="0"}
local five = {l="-", r="0"}
storage.bestHit = storage.bestHit or 0
storage.bestHeal = storage.bestHeal or 0
local lootedItems = {}
local useData = {}
local usedItems ={}
local lastDataSend = {0, 0}
local analyzerButton
local killList = {}
local membersData = {}
HuntingSessionStart = os.date('%Y-%m-%d, %H:%M:%S')
if not storage.analyzers then
storage.analyzers = {
trackedLoot = {},
customPrices = {},
lootChannel = true,
rarityFrames = true
}
end
storage.analyzers = storage.analyzers or {}
storage.analyzers.trackedLoot = storage.analyzers.trackedLoot or {}
local trackedLoot = storage.analyzers.trackedLoot
--destroy old windows
local windowsTable = {"MainAnalyzerWindow", "HuntingAnalyzerWindow", "LootAnalyzerWindow", "SupplyAnalyzerWindow", "ImpactAnalyzerWindow", "XPAnalyzerWindow"}
local windowsTable = {"MainAnalyzerWindow", "HuntingAnalyzerWindow", "LootAnalyzerWindow", "SupplyAnalyzerWindow", "ImpactAnalyzerWindow", "XPAnalyzerWindow", "PartyAnalyzerWindow", "DropTracker"}
for i, window in ipairs(windowsTable) do
local element = g_ui.getRootWidget():recursiveGetChildById(window)
@ -24,31 +68,26 @@ for i, window in ipairs(windowsTable) do
end
local mainWindow = UI.createMiniWindow("MainAnalyzerWindow")
mainWindow:disableResize()
mainWindow:hide()
mainWindow:setContentMaximumHeight(220)
local huntingWindow = UI.createMiniWindow("HuntingAnalyzer")
huntingWindow:hide()
local lootWindow = UI.createMiniWindow("LootAnalyzer")
lootWindow:hide()
lootWindow:setContentMaximumHeight(215)
local supplyWindow = UI.createMiniWindow("SupplyAnalyzer")
supplyWindow:hide()
supplyWindow:setContentMaximumHeight(215)
local impactWindow = UI.createMiniWindow("ImpactAnalyzer")
impactWindow:hide()
impactWindow:setContentMaximumHeight(615)
local xpWindow = UI.createMiniWindow("XPAnalyzer")
xpWindow:hide()
xpWindow:setContentMaximumHeight(230)
local settingsWindow = UI.createWindow("FeaturesWindow")
settingsWindow:hide()
local partyHuntWindow = UI.createMiniWindow("PartyAnalyzerWindow")
partyHuntWindow:hide()
local dropTrackerWindow = UI.createMiniWindow("DropTracker")
dropTrackerWindow:hide()
--f
local toggle = function()
@ -73,6 +112,51 @@ local toggleAnalyzer = function(window)
end
end
local function getSumStats()
local totalWaste = 0
local totalLoot = 0
for k,v in pairs(membersData) do
totalWaste = totalWaste + v.waste
totalLoot = totalLoot + v.loot
end
local totalBalance = totalLoot - totalWaste
return totalWaste, totalLoot, totalBalance
end
local function clipboardData()
local totalWaste, totalLoot, totalBalance = getSumStats()
local final = ""
local first = "Session data: From " .. HuntingSessionStart .." to ".. os.date('%Y-%m-%d, %H:%M:%S')
local second = "Session: " .. sessionTime()
local third = "Loot Type: Market"
local fourth = "Loot " .. format_thousand(totalLoot, true)
local fifth = "Supplies " .. format_thousand(totalWaste, true)
local six = "Balance " .. format_thousand(totalBalance, true)
local t = {first, second, third, fourth, fifth, six}
for i, string in ipairs(t) do
final = final.. "\n"..string
end
--user data now
for k,v in pairs(membersData) do
final = final.. "\n".. k
final = final.. "\n\tLoot "..v.loot
final = final.. "\n\tSupplies "..v.waste
final = final.. "\n\tBalance "..v.balance
final = final.. "\n\tDamage "..v.damage
final = final.. "\n\tHealing "..v.heal
end
g_window.setClipboardText(final)
end
-- create analyzers button
analyzerButton = modules.game_buttons.buttonsWindow.contentsPanel and modules.game_buttons.buttonsWindow.contentsPanel.buttons.botAnalyzersButton
analyzerButton = analyzerButton or modules.client_topmenu.getButton("botAnalyzersButton")
@ -88,6 +172,9 @@ analyzerButton:setOn(false)
mainWindow.contentsPanel.HuntingAnalyzer.onClick = function()
toggleAnalyzer(huntingWindow)
end
mainWindow.onClose = function()
analyzerButton:setOn(false)
end
mainWindow.contentsPanel.LootAnalyzer.onClick = function()
toggleAnalyzer(lootWindow)
end
@ -100,9 +187,14 @@ end
mainWindow.contentsPanel.XPAnalyzer.onClick = function()
toggleAnalyzer(xpWindow)
end
mainWindow.contentsPanel.PartyHunt.onClick = function()
toggleAnalyzer(partyHuntWindow)
end
mainWindow.contentsPanel.DropTracker.onClick = function()
toggleAnalyzer(dropTrackerWindow)
end
--hunting
huntingWindow:setContentMaximumHeight(204)
local sessionTimeLabel = UI.DualLabel("Session:", "00:00h", {}, huntingWindow.contentsPanel).right
local xpGainLabel = UI.DualLabel("XP Gain:", "0", {}, huntingWindow.contentsPanel).right
local xpHourLabel = UI.DualLabel("XP/h:", "0", {}, huntingWindow.contentsPanel).right
@ -113,9 +205,171 @@ local damageLabel = UI.DualLabel("Damage:", "0", {}, huntingWindow.contentsPanel
local damageHourLabel = UI.DualLabel("Damage/h:", "0", {}, huntingWindow.contentsPanel).right
local healingLabel = UI.DualLabel("Healing:", "0", {}, huntingWindow.contentsPanel).right
local healingHourLabel = UI.DualLabel("Healing/h:", "0", {}, huntingWindow.contentsPanel).right
UI.DualLabel("Killed Monsters:", "", {maxWidth = 200}, huntingWindow.contentsPanel)
local killedList = UI.createWidget("AnalyzerListPanel", huntingWindow.contentsPanel)
UI.DualLabel("Looted items:", "", {maxWidth = 200}, huntingWindow.contentsPanel)
local lootList = UI.createWidget("AnalyzerListPanel", huntingWindow.contentsPanel)
--party
UI.Button("Copy to Clipboard", function() clipboardData() end, partyHuntWindow.contentsPanel)
UI.Button("Reset Sessions", function()
if BotServer._websocket then
BotServer.send("partyHunt", false)
end
end, partyHuntWindow.contentsPanel)
local switch = addSwitch("sendData", "Send Analyzer Data", function(widget)
widget:setOn(not widget:isOn())
storage.sendPartyAnalyzerData = widget:isOn()
end, partyHuntWindow.contentsPanel)
switch:setOn(storage.sendPartyAnalyzerData)
UI.Separator(partyHuntWindow.contentsPanel)
local partySessionTimeLabel = UI.DualLabel("Session:", "00:00h", {}, partyHuntWindow.contentsPanel).right
local partyLootLabel = UI.DualLabel("Loot:", "0", {}, partyHuntWindow.contentsPanel).right
local partySuppliesLabel = UI.DualLabel("Supplies:", "0", {}, partyHuntWindow.contentsPanel).right
local partyBalanceLabel = UI.DualLabel("Balance:", "0", {}, partyHuntWindow.contentsPanel).right
UI.Separator(partyHuntWindow.contentsPanel)
local function maintainDropTable()
local panel = dropTrackerWindow.contentsPanel
for k,v in pairs(trackedLoot) do
local widget = panel[k]
if not widget then
trackedLoot[k] = nil
end
end
end
local function createTrackedItems()
local panel = dropTrackerWindow.contentsPanel
for i, child in ipairs(panel:getChildren()) do
if i > 2 then
child:destroy()
end
end
for k,v in pairs(trackedLoot) do
local dropLoot = UI.createWidget("TrackerItem", dropTrackerWindow.contentsPanel)
local item = dropLoot.item
local name = dropLoot.name
local drops = dropLoot.drops
local id = tonumber(k)
local itemName = id == 3031 and "gold coin" or id == 3035 and "platinum coin" or id == 3043 and "crystal coin" or Item.create(id):getMarketData().name
dropLoot:setId(id)
item:setItemId(id)
if item:getItemCount() > 1 then
item:setItemCount(1)
end
name:setText(itemName)
drops:setText("Loot Drops: "..v)
dropLoot.onDoubleClick = function()
local id = dropLoot.item:getItemId()
trackedLoot[tostring(id)] = 0
drops:setText("Loot Drops: 0")
end
for i, child in pairs(dropLoot:getChildren()) do
child:setTooltip("Double click to reset or clear item to remove.")
end
item.onItemChange = function(widget)
local id = widget:getItemId()
if id == 0 then
trackedLoot[widget:getParent():getId()] = nil
if tonumber(widget:getParent():getId()) then
widget:getParent():destroy()
return
end
widget:setImageSource('/images/ui/item')
widget:getParent():setId("blank")
name:setText("Set Item to start track.")
drops:setText("Loot Drops: 0")
return
end
-- only amount have changed, ignore
if tonumber(widget:getParent():getId()) == id then return end
local itemName = id == 3031 and "gold coin" or id == 3035 and "platinum coin" or id == 3043 and "crystal coin" or Item.create(id):getMarketData().name
if trackedLoot[tostring(id)] then
warn("vBot[Drop Tracker]: Item already added!")
name:setText("Set Item to start track.")
widget:setItemId(0)
return
end
widget:setImageSource('')
drops:setText("Loot Drops: 0")
name:setText(itemName)
trackedLoot[tostring(id)] = trackedLoot[tostring(id)] or 0
widget:getParent():setId(id)
maintainDropTable()
end
end
end
--drop tracker
UI.Button("Add item to track drops", function()
local dropLoot = UI.createWidget("TrackerItem", dropTrackerWindow.contentsPanel)
local item = dropLoot.item
local name = dropLoot.name
local drops = dropLoot.drops
item:setImageSource('/images/ui/item')
dropLoot.onDoubleClick = function()
local id = dropLoot.item:getItemId()
trackedLoot[tostring(id)] = 0
drops:setText("Loot Drops: 0")
end
for i, child in pairs(dropLoot:getChildren()) do
child:setTooltip("Double click to reset or clear item to remove.")
end
item.onItemChange = function(widget)
local id = widget:getItemId()
if id == 0 then
trackedLoot[widget:getParent():getId()] = nil
if tonumber(widget:getParent():getId()) then
widget:getParent():destroy()
return
end
widget:setImageSource('/images/ui/item')
widget:getParent():setId("blank")
name:setText("Set Item to start track.")
drops:setText("Loot Drops: 0")
return
end
-- only amount have changed, ignore
if tonumber(widget:getParent():getId()) == id then return end
local itemName = id == 3031 and "gold coin" or id == 3035 and "platinum coin" or id == 3043 and "crystal coin" or Item.create(id):getMarketData().name
if trackedLoot[tostring(id)] then
warn("vBot[Drop Tracker]: Item already added!")
name:setText("Set Item to start track.")
widget:setItemId(0)
return
end
widget:setImageSource('')
drops:setText("Loot Drops: 0")
name:setText(itemName)
trackedLoot[tostring(id)] = trackedLoot[tostring(id)] or 0
widget:getParent():setId(id)
maintainDropTable()
end
end, dropTrackerWindow.contentsPanel)
UI.Separator(dropTrackerWindow.contentsPanel)
createTrackedItems()
--loot
@ -240,14 +494,18 @@ local function getColor(v)
return "#5F8DF7"
elseif v >= 1000 then -- 1k, green
return "#00FF00"
elseif v >= 50 then
return "#FFFFFF" -- 50gp, white
else
return "#FFFFFF" -- less than 1k, white
return "#aaaaaa" -- less than 100gp, grey
end
end
local function formatStr(str)
if string.starts(str, "a ") then
str = str:sub(2, #str)
elseif string.starts(str, "an ") then
str = str:sub(3, #str)
end
local n = getFirstNumberInText(str)
@ -261,6 +519,7 @@ end
local function getPrice(name)
name = formatStr(name)
name = name:lower()
-- first check custom prices
if storage.analyzers.customPrices[name] then
return storage.analyzers.customPrices[name]
@ -289,6 +548,57 @@ local function getPrice(name)
return 0
end
local expGained = function()
return exp() - startExp
end
function format_thousand(v, comma)
comma = comma and "," or "."
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), "(...)", comma.."%1")
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
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
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 function add(t, text, color, last)
table.insert(t, text)
table.insert(t, color)
@ -298,9 +608,147 @@ local function add(t, text, color, last)
end
end
-- Bot Server
local function sendData()
if BotServer._websocket then
local totalDmg, totalHeal, lootWorth, wasteWorth, balance = getHuntingData()
local outfit = player:getOutfit()
outfit.mount = 0
local t = {
totalDmg,
totalHeal,
balance,
hppercent(),
manapercent(),
outfit,
player:isPartyLeader(),
lootWorth,
wasteWorth,
modules.game_skills.skillsWindow.contentsPanel.stamina.value:getText(),
format_thousand(expGained()),
expPerHour(),
balanceDesc .. " (" .. hourDesc .. ")",
sessionTime()
}
-- validation
if lastDataSend.totalDmg ~= t[1] and lastDataSend.totalHeal ~= t[2] then
BotServer.send("partyHunt", t)
lastDataSend[1] = t[1]
lastDataSend[2] = t[2]
end
end
end
-- process data
BotServer.listen("partyHunt", function(name, message)
if message == true then
sendData()
elseif message == false then
resetAnalyzerSessionData()
else
membersData[name] = {
damage = message[1],
heal = message[2],
balance = message[3],
hp = message[4],
mana = message[5],
outfit = message[6],
leader = message[7],
loot = message[8],
waste = message[9],
stamina = message[10],
expGained = message[11],
expH = message[12],
balanceH = message[13],
session = message[14]
}
local widgetName = "Widget"..name
local widget = partyHuntWindow.contentsPanel[widgetName] or UI.createWidget("MemberWidget", partyHuntWindow.contentsPanel)
widget:setId(widgetName)
widget.lastUpdate = now
local t = membersData[name]
widget.name:setText(name)
widget.name:setColor("white")
if t.leader then
widget.name:setColor('#f8db38')
end
schedule(10*1000, function()
if widget and widget.lastUpdate and now - widget.lastUpdate > 10000 then
widget.name:setText(widget.name:getText().. " [inactive]")
widget.name:setColor("#aeaeae")
widget.health:setBackgroundColor("#aeaeae")
widget.mana:setBackgroundColor("#aeaeae")
widget.balance.value:setText("-")
widget.damage.value:setText("-")
widget.healing.value:setText("-")
widget.creature:disable()
end
end)
widget.creature:setOutfit(t.outfit)
widget.health:setPercent(t.hp)
widget.health:setBackgroundColor("#00c000")
widget.mana:setPercent(t.mana)
widget.mana:setBackgroundColor("#0000FF")
widget.balance.value:setText(format_thousand(t.balance))
if t.balance < 0 then
widget.balance.value:setColor('#ff9854')
elseif t.balance > 0 then
widget.balance.value:setColor('#45ad25')
else
widget.balance.value:setColor('white')
end
widget.damage.value:setText(format_thousand(t.damage))
widget.healing.value:setText(format_thousand(t.heal))
widget.onDoubleClick = function()
membersData[name] = nil
widget:destroy()
end
--tooltip
local tooltip = "Session: "..t.session.."\n"..
"Stamina: "..t.stamina.."\n"..
"Exp Gained: "..t.expGained.."\n"..
"Exp per Hour: "..t.expH.."\n"..
"Balance: "..t.balanceH
widget.creature:setTooltip(tooltip)
end
end)
function hightlightText(widget, color, duration)
for i=0,duration do
schedule(i * 250, function()
if i == duration or (i > 0 and i % 2 == 0) then
widget:setColor("#FFFFFF")
else
widget:setColor(color)
end
end)
end
end
local nameRegex = [[Loot of (?:an |a |the |)([^:]+)]]
onTextMessage(function(mode, text)
if not storage.analyzers.lootChannel then return end
if not text:find("Loot of") and not text:find("The following items are available in your reward chest") then return end
local name
-- adding monster to killed list
if text:find("Loot of") then
name = regexMatch(text, nameRegex)[1][2]
if not killList[name] then
killList[name] = 1
else
killList[name] = killList[name] + 1
end
refreshKills()
end
-- variables
local split = string.split(text, ":")
local re = regexMatch(split[2], regex)
@ -308,21 +756,50 @@ onTextMessage(function(mode, text)
local formatted
local div
local t = {}
local messageT = {}
-- add timestamp, creature part and color it as white
add(t, os.date('%H:%M') .. ' ' .. split[1]..": ", "#FFFFFF", true)
add(messageT, split[1]..": ", "#FFFFFF", true)
-- main part
if re ~= 0 then
for i=1,#re do
local data = re[i][2] -- each looted item
local amount = getFirstNumberInText(data) -- amount found in data
local price = amount and getPrice(data) * amount or getPrice(data) -- if amount then multity price, else just take price
local formattedLoot = regexMatch(data, [[(^[^(]+)]])[1][1]
formattedLoot = formattedLoot:trim()
local amount = getFirstNumberInText(formattedLoot) -- amount found in data
local price = amount and getPrice(formattedLoot) * amount or getPrice(formattedLoot) -- if amount then multity price, else just take price
local color = getColor(price) -- generate hex string based off price
local messageColor = getColor(getPrice(formattedLoot))
combinedWorth = combinedWorth + price -- add all prices to calculate total worth
add(t, data, color, i==#re)
add(messageT, data, color, i==#re)
--drop tracker
for i, child in ipairs(dropTrackerWindow.contentsPanel:getChildren()) do
local childName = child.name
childName = childName and childName:getText()
if childName and formattedLoot:find(childName) then
trackedLoot[tostring(child.item:getItemId())] = trackedLoot[tostring(child.item:getItemId())] + (amount or 1)
child.drops:setText("Loot Drops: "..trackedLoot[tostring(child.item:getItemId())])
hightlightText(child.name,"#f0b400", 8)
modules.game_textmessage.messagesPanel.statusLabel:setVisible(true)
modules.game_textmessage.messagesPanel.statusLabel:setColoredText({
"Valuable loot: ", "#f0b400",
childName.."", messageColor,
" dropped by "..name.."!", "#f0b400"
})
schedule(3000, function()
modules.game_textmessage.messagesPanel.statusLabel:setVisible(false)
end)
end
end
end
end
@ -337,6 +814,13 @@ onTextMessage(function(mode, text)
formatted = combinedWorth .. "gp"
end
if modules.game_textmessage.messagesPanel.centerTextMessagePanel.highCenterLabel:getText() == text then
modules.game_textmessage.messagesPanel.centerTextMessagePanel.highCenterLabel:setColoredText(messageT)
schedule(math.max(#text * 50, 2000), function()
modules.game_textmessage.messagesPanel.centerTextMessagePanel.highCenterLabel:setVisible(false)
end)
end
-- add total worth to string
add(t, " - (", "#FFFFFF", true)
add(t, formatted, getColor(combinedWorth), true)
@ -375,27 +859,7 @@ local function niceFormat(v)
return formatted
end
local launchTime = now
local startExp = exp()
local dmgTable = {}
local healTable = {}
local expTable = {}
local totalDmg = 0
local totalHeal = 0
local dmgDistribution = {}
local first = {l="-", r="0"}
local second = {l="-", r="0"}
local third = {l="-", r="0"}
local fourth = {l="-", r="0"}
local five = {l="-", r="0"}
storage.bestHit = storage.bestHit or 0
storage.bestHeal = storage.bestHeal or 0
local lootedItems = {}
local useData = {}
local usedItems ={}
local resetSessionData = function()
resetAnalyzerSessionData = function()
launchTime = now
startExp = exp()
dmgTable = {}
@ -424,10 +888,13 @@ local resetSessionData = function()
drawGraph(dmgGraph, 0)
healGraph:clear()
drawGraph(healGraph, 0)
killList = {}
refreshKills()
HuntingSessionStart = os.date('%Y-%m-%d, %H:%M:%S')
end
mainWindow.contentsPanel.ResetSession.onClick = function()
resetSessionData()
resetAnalyzerSessionData()
end
mainWindow.contentsPanel.Settings.onClick = function()
@ -442,22 +909,14 @@ settingsWindow.closeButton.onClick = function()
settingsWindow:hide()
end
if not storage.analyzers then
storage.analyzers = {
customPrices = {},
lootChannel = true,
rarityFrames = true
}
end
local function getFrame(v)
if v > 1000000 then
if v >= 1000000 then
return '/images/ui/rarity_gold'
elseif v > 100000 then
elseif v >= 100000 then
return '/images/ui/rarity_purple'
elseif v > 10000 then
elseif v >= 10000 then
return '/images/ui/rarity_blue'
elseif v > 1000 then
elseif v >= 1000 then
return '/images/ui/rarity_green'
else
return '/images/ui/item'
@ -568,63 +1027,6 @@ settingsWindow.RarityFrames.onClick = function(widget)
setFrames()
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
@ -772,9 +1174,11 @@ end
function refreshLoot()
lootItems.List:destroyChildren()
lootItems:destroyChildren()
lootList:destroyChildren()
for k,v in pairs(lootedItems) do
local label1 = UI.createWidget("AnalyzerLootItem", lootItems.List)
local label1 = UI.createWidget("AnalyzerLootItem", lootItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
label1:setItemId(k)
@ -784,17 +1188,38 @@ function refreshLoot()
label1.count:setColor(getColor(price))
local tooltipName = v.count > 1 and v.name.."s" or v.name
label1:setTooltip(v.count .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)")
--hunting window loot list
local label2 = UI.createWidget("ListLabel", lootList)
label2:setText(v.count .. "x " .. v.name)
end
if lootItems:getChildCount() == 0 then
local label = UI.createWidget("ListLabel", lootList)
label:setText("None")
end
local height = getPanelHeight(lootItems)
lootItems:setHeight(height)
lootWindow:setContentMaximumHeight(height+220)
end
refreshLoot()
function refreshKills()
killedList:destroyChildren()
local kills = 0
for k,v in pairs(killList) do
kills = kills + 1
local label = UI.createWidget("ListLabel", killedList)
label:setText(v .. "x " .. k)
end
if kills == 0 then
local label = UI.createWidget("ListLabel", killedList)
label:setText("None")
end
end
refreshKills()
function refreshWaste()
supplyItems.List:destroyChildren()
supplyItems:destroyChildren()
for k,v in pairs(usedItems) do
local label1 = UI.createWidget("AnalyzerLootItem", supplyItems.List)
local label1 = UI.createWidget("AnalyzerLootItem", supplyItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
label1:setItemId(k)
@ -805,13 +1230,8 @@ function refreshWaste()
local tooltipName = v.count > 1 and v.name.."s" or v.name
label1:setTooltip(v.count .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)")
end
local height = getPanelHeight(supplyItems)
supplyItems:setHeight(height)
supplyWindow:setContentMaximumHeight(height+215)
end
-- loot analyzer
-- adding
local containers = CaveBot.GetLootContainers()
@ -821,7 +1241,6 @@ onAddItem(function(container, slot, item, oldItem)
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
local name = item:getId()
local tmpname = 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
@ -831,6 +1250,8 @@ onAddItem(function(container, slot, item, oldItem)
end
lastCap = freecap()
refreshLoot()
-- drop tracker
end)
onContainerUpdateItem(function(container, slot, item, oldItem)
@ -894,6 +1315,8 @@ onTextMessage(function(mode, text)
else
usedItems[id].count = usedItems[id].count + 1
end
else
useData[name] = amount
end
refreshWaste()
end
@ -904,15 +1327,6 @@ 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
@ -1008,6 +1422,11 @@ function lootHour()
end
end
function getHuntingData()
local lootWorth, wasteWorth, balance = bottingStats()
return totalDmg, totalHeal, lootWorth, wasteWorth, balance
end
--bestdps/hps
local bestDPS = 0
local bestHPS = 0
@ -1029,7 +1448,7 @@ macro(500, function()
xpHourLabel:setText(expPerHour())
lootLabel:setText(format_thousand(lootWorth))
suppliesLabel:setText(format_thousand(wasteWorth))
balanceLabel:setColor(balance >= 0 and "green" or "red")
balanceLabel:setColor(balance >= 0 and "#45ad25" or "#ff9854")
balanceLabel:setText(balanceDesc .. " (" .. hourDesc .. ")")
damageLabel:setText(format_thousand(totalDmg))
damageHourLabel:setText(format_thousand(damageHour()))
@ -1081,3 +1500,80 @@ macro(60*1000, function()
drawGraph(dmgGraph, valueInSeconds(dmgTable) or 0)
drawGraph(healGraph, valueInSeconds(healTable) or 0)
end)
--party hunt analyzer
macro(2000, function()
if not BotServer._websocket then return end
-- send data
if storage.sendPartyAnalyzerData then
sendData()
end
local totalWaste, totalLoot, totalBalance = getSumStats()
partySessionTimeLabel:setText(sessionTime())
partyLootLabel:setText(format_thousand(totalLoot))
partySuppliesLabel:setText(format_thousand(totalWaste))
partyBalanceLabel:setText(format_thousand(totalBalance))
if totalBalance < 0 then
partyBalanceLabel:setColor('#ff9854')
elseif totalBalance > 0 then
partyBalanceLabel:setColor('#45ad25')
else
partyBalanceLabel:setColor('white')
end
end)
-- public functions
-- global namespace
Analyzer = {}
Analyzer.getKillsAmount = function(name)
return killList[name] or 0
end
Analyzer.getLootedAmount = function(nameOrId)
if type(nameOrId) == "number" then
return lootedItems[nameOrId].count or 0
else
local nameOrId = nameOrId:lower()
for k,v in pairs(lootedItems) do
if v.name == nameOrId then
return v.count
end
end
end
return 0
end
Analyzer.getTotalProfit = function()
local lootWorth, wasteWorth, balance = bottingStats()
return lootWorth
end
Analyzer.getTotalWaste = function()
local lootWorth, wasteWorth, balance = bottingStats()
return wasteWorth
end
Analyzer.getBalance = function()
local lootWorth, wasteWorth, balance = bottingStats()
return balance
end
Analyzer.getXpGained = function()
return expGained()
end
Analyzer.getXpHour = function()
return expPerHour()
end
Analyzer.getTimeToNextLevel = function()
return timeToLevel()
end

View File

@ -1,3 +1,121 @@
TrackerItem < Panel
height: 40
BotItem
id: item
anchors.top: parent.top
margin-top: 2
anchors.left: parent.left
image-source:
UIWidget
id: name
anchors.top: prev.top
margin-top: 1
anchors.bottom: prev.verticalCenter
anchors.left: prev.right
anchors.right: parent.right
margin-left: 5
text: Set Item to start track.
text-align:left
font: verdana-11px-rounded
color: #FFFFFF
UIWidget
id: drops
anchors.top: prev.bottom
margin-top: 3
anchors.bottom: Item.bottom
anchors.left: prev.left
anchors.right: parent.right
font: verdana-11px-rounded
text-align:left
text: Loot Drops: 0
color: #CCCCCC
DualLabel < Label
height: 15
text-offset: 4 0
font: verdana-11px-rounded
text-align: left
width: 50
Label
id: value
anchors.right: parent.right
margin-right: 4
anchors.verticalCenter: parent.verticalCenter
width: 200
font: verdana-11px-rounded
text-align: right
text: 0
MemberWidget < Panel
height: 85
margin-top: 3
UICreature
id: creature
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
size: 28 28
UIWidget
id: name
anchors.left: prev.right
margin-left: 5
anchors.top: parent.top
height: 12
anchors.right: parent.right
text: Player Name
font: verdana-11px-rounded
text-align: left
ProgressBar
id: health
anchors.left: prev.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
height: 7
background-color: #00c000
phantom: false
ProgressBar
id: mana
anchors.left: prev.left
anchors.right: parent.right
anchors.top: prev.bottom
height: 7
background-color: #0000FF
phantom: false
DualLabel
id: balance
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
text: Balance:
DualLabel
id: damage
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 2
text: Damage:
DualLabel
id: healing
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 2
text: Healing:
AnalyzerPriceLabel < Label
background-color: alpha
text-offset: 2 0
@ -15,19 +133,28 @@ AnalyzerPriceLabel < Label
width: 15
height: 15
AnalyzerItemsPanel < Panel
height: 0
AnalyzerListPanel < Panel
padding-left: 4
padding-right: 4
layout:
type: verticalBox
fit-children: true
Panel
ListLabel < Label
height: 15
font: verdana-11px-rounded
text-offset: 15 0
AnalyzerItemsPanel < Panel
id: List
anchors.fill: parent
margin-top: 3
padding: 2
layout:
type: grid
cell-size: 32 32
cell-spacing: 3
cell-size: 33 33
cell-spacing: 1
num-columns: 5
fit-children: true
AnalyzerLootItem < UIItem
opacity: 0.87
@ -79,7 +206,7 @@ AnalyzerButton < Button
MainAnalyzerWindow < MiniWindow
id: MainAnalyzerWindow
text: Analytics Selector
height: 200
height: 245
icon: /images/topbuttons/analyzers
MiniWindowContents
@ -108,6 +235,15 @@ MainAnalyzerWindow < MiniWindow
id: XPAnalyzer
text: XP Analyzer
AnalyzerButton
id: DropTracker
text: Drop Tracker
AnalyzerButton
id: PartyHunt
text: Party Hunt
color: #3895D3
AnalyzerButton
id: Settings
text: Features & Settings
@ -164,6 +300,29 @@ XPAnalyzer < MiniWindow
padding-top: 3
layout: verticalBox
PartyAnalyzerWindow < MiniWindow
id: PartyAnalyzerWindow
text: Party Hunt
height: 200
icon: /images/topbuttons/analyzers
MiniWindowContents
padding-left: 3
padding-right: 3
padding-top: 1
layout: verticalBox
DropTracker < MiniWindow
id: DropTracker
text: Drop Tracker
height: 200
icon: /images/topbuttons/analyzers
MiniWindowContents
padding-left: 3
padding-right: 3
padding-top: 1
layout: verticalBox
FeaturesWindow < MainWindow
id: FeaturesWindow

View File

@ -4,10 +4,11 @@ local m = macro(1000, "AntiRS & Msg", function() end)
local frags = 0
onTextMessage(function(mode, text)
if not m.isOn() then return end
if not text:lower():find("warning! the murder of") then return end
if not text:find("Warning! The murder of") then return end
say("Don't bother, I have anti-rs and shit EQ. Don't waste our time.")
frags = frags + 1
if killsToRs() < 6 or frags > 1 then
g_game.stop()
modules.game_interface.forceExit()
end
end)

View File

@ -9,12 +9,22 @@ if not g_resources.directoryExists("/bot/".. configName .."/vBot_configs/") then
g_resources.makeDir("/bot/".. configName .."/vBot_configs/")
end
-- make profile dirs
for i=1,10 do
local path = "/bot/".. configName .."/vBot_configs/profile_"..i
if not g_resources.directoryExists(path) then
g_resources.makeDir(path)
end
end
local profile = g_settings.getNumber('profile')
HealBotConfig = {}
local healBotFile = "/bot/" .. configName .. "/vBot_configs/".. name() .. " HealBot.json"
local healBotFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/HealBot.json"
AttackBotConfig = {}
local attackBotFile = "/bot/" .. configName .. "/vBot_configs/".. name() .. " AttackBot.json"
local attackBotFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/AttackBot.json"
SuppliesConfig = {}
local suppliesFile = "/bot/" .. configName .. "/vBot_configs/".. name() .. " Supplies.json"
local suppliesFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/Supplies.json"
--healbot

View File

@ -0,0 +1,123 @@
setDefaultTab("Cave")
local panelName = "specialDeposit"
local depositerPanel
UI.Button("Stashing Settings", function()
depositerPanel:show()
depositerPanel:raise()
depositerPanel:focus()
end)
if not storage[panelName] then
storage[panelName] = {
items = {},
height = 380
}
end
local config = storage[panelName]
depositerPanel = UI.createWindow('DepositerPanel', rootWidget)
depositerPanel:hide()
-- basic one
depositerPanel.CloseButton.onClick = function()
depositerPanel:hide()
end
depositerPanel:setHeight(config.height or 380)
depositerPanel.onGeometryChange = function(widget, old, new)
if old.height == 0 then return end
config.height = new.height
end
function arabicToRoman(n)
local t = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XI", "XII", "XIV", "XV", "XVI", "XVII"}
return t[n]
end
local function refreshEntries()
depositerPanel.DepositerList:destroyChildren()
for _, entry in ipairs(config.items) do
local panel = g_ui.createWidget("StashItem", depositerPanel.DepositerList)
panel.name:setText(Item.create(entry.id):getMarketData().name)
for i, child in ipairs(panel:getChildren()) do
if child:getId() ~= "slot" then
child:setTooltip("Clear item or double click to remove entry.")
child.onDoubleClick = function(widget)
table.remove(config.items, table.find(entry))
panel:destroy()
end
end
end
panel.item:setItemId(entry.id)
if entry.id > 0 then
panel.item:setImageSource('')
end
panel.item.onItemChange = function(widget)
local id = widget:getItemId()
if id < 100 then
table.remove(config.items, table.find(entry))
panel:destroy()
else
for i, data in ipairs(config.items) do
if data.id == id then
warn("[Depositer Panel] Item already added!")
return
end
end
entry.id = id
panel.item:setImageSource('')
panel.name:setText(Item.create(entry.id):getMarketData().name)
if entry.index == 0 then
local window = modules.client_textedit.show(panel.slot, {
title = "Set depot for "..panel.name:getText(),
description = "Select depot to which item should be stashed, choose between 3 and 17",
validation = [[^([3-9]|1[0-7])$]]
})
window.text:setText(entry.index)
schedule(50, function()
window:raise()
window:focus()
end)
end
end
end
if entry.id > 0 then
panel.slot:setText("Stash to depot: ".. entry.index)
end
panel.slot:setTooltip("Click to set stashing destination.")
panel.slot.onClick = function(widget)
local window = modules.client_textedit.show(widget, {
title = "Set depot for "..panel.name:getText(),
description = "Select depot to which item should be stashed, choose between 3 and 17",
validation = [[^([3-9]|1[0-7])$]]
})
window.text:setText(entry.index)
schedule(50, function()
window:raise()
window:focus()
end)
end
panel.slot.onTextChange = function(widget, text)
local n = tonumber(text)
if n then
entry.index = n
widget:setText("Stash to depot: "..entry.index)
end
end
end
end
refreshEntries()
depositerPanel.title.onDoubleClick = function(widget)
table.insert(config.items, {id=0, index=0})
refreshEntries()
end
function getStashingIndex(id)
for _, v in pairs(config.items) do
if v.id == id then
return v.index - 1
end
end
end

View File

@ -0,0 +1,99 @@
StashItem < Panel
height: 40
BotItem
id: item
anchors.top: parent.top
margin-top: 2
anchors.left: parent.left
UIWidget
id: name
anchors.top: prev.top
margin-top: 1
anchors.bottom: prev.verticalCenter
anchors.left: prev.right
anchors.right: parent.right
margin-left: 5
text-align:left
text: item name
font: verdana-11px-rounded
color: #FFFFFF
UIWidget
id: slot
anchors.top: prev.bottom
margin-top: 3
anchors.bottom: Item.bottom
anchors.left: prev.left
anchors.right: parent.right
font: verdana-11px-rounded
text-align:left
text: Add item to select locker.
color: #CCCCCC
DepositerPanel < MainWindow
size: 230 380
!text: tr('Depositer Panel')
@onEscape: self:hide()
UIWidget
id: title
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text: Double click here to add item.
text-align: left
font: verdana-11px-rounded
color: #aeaeae
ScrollablePanel
id: DepositerList
image-source: /images/ui/panel_flat
image-border: 1
anchors.top: prev.bottom
margin-top: 5
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: sep.top
margin-bottom: 10
padding: 2
padding-left: 4
vertical-scrollbar: DepositerScrollBar
layout:
type: verticalBox
VerticalScrollBar
id: DepositerScrollBar
anchors.top: DepositerList.top
anchors.bottom: DepositerList.bottom
anchors.right: DepositerList.right
step: 14
pixels-scroll: true
visible: false
ResizeBorder
id: bottomResizeBorder
anchors.fill: next
height: 3
minimum: 180
maximum: 800
margin-left: 3
margin-right: 3
background: #ffffff88
HorizontalSeparator
id: sep
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-right: 5

View File

@ -70,7 +70,7 @@ Rule < UIWidget
ConditionPanel < Panel
height: 55
height: 53
NexButton
id: nex
@ -115,12 +115,8 @@ ConditionPanel < Panel
ListPanel < FlatPanel
size: 270 265
size: 270 300
padding-left: 10
padding-right: 10
padding-bottom: 10
@ -218,10 +214,8 @@ Unequip < Panel
InputPanel < FlatPanel
size: 270 265
size: 270 300
padding-left: 10
padding-right: 10
padding-bottom: 10
@ -240,12 +234,12 @@ InputPanel < FlatPanel
anchors.right: parent.right
anchors.top: parent.top
margin-top: 10
height: 40
height: 80
layout:
type: grid
cell-size: 34 34
cell-spacing: 2
num-columns: 9
num-columns: 7
Button
id: unequip
@ -303,7 +297,7 @@ InputPanel < FlatPanel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 8
margin-top: 3
HorizontalSeparator
anchors.left: parent.left
@ -336,7 +330,7 @@ InputPanel < FlatPanel
tooltip: On add above rule will be listed as Profile name - use friendly one!
EquipWindow < MainWindow
size: 600 345
size: 600 370
text: Equipment Manager
@onEscape: self:hide()

View File

@ -7,7 +7,7 @@ if voc == 1 or voc == 11 then
onCreatureHealthPercentChange(function(creature, healthPercent)
if m.isOff() then return end
if healthPercent > 15 then return end
if CaveBot.isOff() or TargetBot.isOff() or not isBuffed() then return end
if CaveBot.isOff() or TargetBot.isOff() then return end
if modules.game_cooldown.isGroupCooldownIconActive(3) then return end
if creature:getPosition() and getDistanceBetween(pos(),creature:getPosition()) > 1 then return end
if canCast("exeta res") and now - lastCast > 6000 then

View File

@ -19,13 +19,24 @@ local rightPanel = extrasWindow.content.right
local leftPanel = extrasWindow.content.left
-- objects made by Kondrah - taken from creature editor, minor changes to adapt
local addCheckBox = function(id, title, defaultValue, dest)
local addCheckBox = function(id, title, defaultValue, dest, tooltip)
local widget = UI.createWidget('ExtrasCheckBox', dest)
widget.onClick = function()
widget:setOn(not widget:isOn())
settings[id] = widget:isOn()
if id == "checkPlayer" then
local label = rootWidget.newHealer.targetSettings.vocations.title
if not widget:isOn() then
label:setColor("#d9321f")
label:setTooltip("! WARNING ! \nTurn on check players in extras to use this feature!")
else
label:setColor("#dfdfdf")
label:setTooltip("")
end
end
end
widget:setText(title)
widget:setTooltip(tooltip)
if settings[id] == nil then
widget:setOn(defaultValue)
else
@ -34,9 +45,11 @@ local addCheckBox = function(id, title, defaultValue, dest)
settings[id] = widget:isOn()
end
local addItem = function(id, title, defaultItem, dest)
local addItem = function(id, title, defaultItem, dest, tooltip)
local widget = UI.createWidget('ExtrasItem', dest)
widget.text:setText(title)
widget.text:setTooltip(tooltip)
widget.item:setTooltip(tooltip)
widget.item:setItemId(settings[id] or defaultItem)
widget.item.onItemChange = function(widget)
settings[id] = widget:getItemId()
@ -44,18 +57,20 @@ local addItem = function(id, title, defaultItem, dest)
settings[id] = settings[id] or defaultItem
end
local addTextEdit = function(id, title, defaultValue, dest)
local addTextEdit = function(id, title, defaultValue, dest, tooltip)
local widget = UI.createWidget('ExtrasTextEdit', dest)
widget.text:setText(title)
widget.textEdit:setText(settings[id] or defaultValue or "")
widget.text:setTooltip(tooltip)
widget.textEdit.onTextChange = function(widget,text)
settings[id] = text
end
settings[id] = settings[id] or defaultValue or ""
end
local addScrollBar = function(id, title, min, max, defaultValue, dest)
local addScrollBar = function(id, title, min, max, defaultValue, dest, tooltip)
local widget = UI.createWidget('ExtrasScrollBar', dest)
widget.text:setTooltip(tooltip)
widget.scroll.onValueChange = function(scroll, value)
widget.text:setText(title .. ": " .. value)
if value == 0 then
@ -64,6 +79,7 @@ local addScrollBar = function(id, title, min, max, defaultValue, dest)
settings[id] = value
end
widget.scroll:setRange(min, max)
widget.scroll:setTooltip(tooltip)
if max-min > 1000 then
widget.scroll:setStep(100)
elseif max-min > 100 then
@ -86,20 +102,20 @@ UI.Separator()
--- add callback (optional)
--- optionals should be addionaly sandboxed (if true then end)
addItem("rope", "Rope Item", 9596, leftPanel)
addItem("shovel", "Shovel Item", 9596, leftPanel)
addItem("machete", "Machete Item", 9596, leftPanel)
addItem("scythe", "Scythe Item", 9596, leftPanel)
addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel)
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel)
addScrollBar("huntRoutes", "Hunting Routes Limit", 0, 300, 50, leftPanel)
addScrollBar("killUnder", "Kill monsters below", 0, 100, 1, leftPanel)
addScrollBar("gotoMaxDistance", "Max GoTo Distance", 0, 127, 30, 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)
addItem("rope", "Rope Item", 9596, leftPanel, "This item will be used in various bot related scripts as default rope item.")
addItem("shovel", "Shovel Item", 9596, leftPanel, "This item will be used in various bot related scripts as default shovel item.")
addItem("machete", "Machete Item", 9596, leftPanel, "This item will be used in various bot related scripts as default machete item.")
addItem("scythe", "Scythe Item", 9596, leftPanel, "This item will be used in various bot related scripts as default scythe item.")
addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel, "Breaks between each talk action in cavebot (time in miliseconds).")
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel, "Every loot corpse futher than set distance (in sqm) will be ignored and forgotten.")
addScrollBar("huntRoutes", "Hunting Rounds Limit", 0, 300, 50, leftPanel, "Round limit for supply check, if character already made more rounds than set, on next supply check will return to city.")
addScrollBar("killUnder", "Kill monsters below", 0, 100, 1, leftPanel, "Force TargetBot to kill added creatures when they are below set percentage of health - will ignore all other TargetBot settings.")
addScrollBar("gotoMaxDistance", "Max GoTo Distance", 0, 127, 30, leftPanel, "Maximum distance to next goto waypoint for the bot to try to reach.")
addCheckBox("lootLast", "Start loot from last corpse", true, leftPanel, "Looting sequence will be reverted and bot will start looting newest bodies.")
addCheckBox("joinBot", "Join TargetBot and CaveBot", false, leftPanel, "Cave and Target tabs will be joined into one.")
addCheckBox("reachable", "Target only pathable mobs", false, leftPanel, "Ignore monsters that can't be reached.")
addCheckBox("title", "Custom Window Title", true, rightPanel)
addCheckBox("title", "Custom Window Title", true, rightPanel, "Personalize OTCv8 window name according to character specific.")
if true then
local vocText = ""
@ -126,7 +142,7 @@ if true then
end)
end
addCheckBox("separatePm", "Open PM's in new Window", false, rightPanel)
addCheckBox("separatePm", "Open PM's in new Window", false, rightPanel, "PM's will be automatically opened in new tab after receiving one.")
if true then
onTalk(function(name, level, mode, text, channelId, pos)
if mode == 4 and settings.separatePm then
@ -141,7 +157,7 @@ if true then
end)
end
addTextEdit("useAll", "Use All Hotkey", "space", rightPanel)
addTextEdit("useAll", "Use All Hotkey", "space", rightPanel, "Set hotkey for universal actions - rope, shovel, scythe, use, open doors")
if true then
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,
@ -149,7 +165,7 @@ if true then
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,
5736, 6264, 31262, 31130, 31129, 6250, 6249, 5122, 30049, 7131, 7132, 7727 }
local shovelId = { 606, 593, 867 }
local shovelId = { 606, 593, 867, 608 }
local ropeId = { 17238, 12202, 12935, 386, 421, 21966, 14238 }
local macheteId = { 2130, 3696 }
local scytheId = { 3653 }
@ -187,7 +203,7 @@ if true then
end
addCheckBox("timers", "MW & WG Timers", true, rightPanel)
addCheckBox("timers", "MW & WG Timers", true, rightPanel, "Show times for Magic Walls and Wild Growths.")
if true then
local activeTimers = {}
@ -226,7 +242,7 @@ if true then
end
addCheckBox("antiKick", "Anti - Kick", true, rightPanel)
addCheckBox("antiKick", "Anti - Kick", true, rightPanel, "Turn every 10 minutes to prevent kick.")
if true then
macro(600*1000, function()
if not settings.antiKick then return end
@ -237,7 +253,7 @@ if true then
end
addCheckBox("stake", "Skin Monsters", false, leftPanel)
addCheckBox("stake", "Skin Monsters", false, leftPanel, "Automatically skin & stake corpses when cavebot is enabled")
if true then
local knifeBodies = {4286, 4272, 4173, 4011, 4025, 4047, 4052, 4057, 4062, 4112, 4212, 4321, 4324, 4327, 10352, 10356, 10360, 10364}
local stakeBodies = {4097, 4137, 8738, 18958}
@ -245,7 +261,8 @@ if true then
macro(500, function()
if not CaveBot.isOn() or not settings.stake then return end
for i, tile in ipairs(g_map.getTiles(posz())) do
for u,item in ipairs(tile:getItems()) do
local item = tile:getTopThing()
if item and item:isContainer() then
if table.find(knifeBodies, item:getId()) and findItem(5908) then
CaveBot.delay(550)
useWith(5908, item)
@ -267,13 +284,13 @@ if true then
end
addCheckBox("oberon", "Auto Reply Oberon", true, rightPanel)
addCheckBox("oberon", "Auto Reply Oberon", true, rightPanel, "Auto reply to Grand Master Oberon talk minigame.")
if true then
onTalk(function(name, level, mode, text, channelId, pos)
if not settings.oberon then return end
if mode == 34 then
if string.find(text, "world will suffer for") then
say("Are you ever going to fight or do you prefer talking!")
say("Are you ever going to fight or do you prefer talking?")
elseif string.find(text, "feet when they see me") then
say("Even before they smell your breath?")
elseif string.find(text, "from this plane") then
@ -296,9 +313,8 @@ if true then
end
addCheckBox("autoOpenDoors", "Auto Open Doors", true, rightPanel)
addCheckBox("autoOpenDoors", "Auto Open Doors", true, rightPanel, "Open doors when trying to step on them.")
if true then
local wsadWalking = modules.game_walking.wsadWalking
local doorsIds = { 5007, 8265, 1629, 1632, 5129, 6252, 6249, 7715, 7712, 7714,
7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642,
6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116,
@ -316,6 +332,7 @@ if true then
end
onKeyPress(function(keys)
local wsadWalking = modules.game_walking.wsadWalking
if not settings.autoOpenDoors then return end
local pos = player:getPosition()
if keys == 'Up' or (wsadWalking and keys == 'W') then
@ -344,7 +361,7 @@ if true then
end
addCheckBox("bless", "Buy bless at login", true, rightPanel)
addCheckBox("bless", "Buy bless at login", true, rightPanel, "Say !bless at login.")
if true then
local blessed = false
onTextMessage(function(mode,text)
@ -371,7 +388,7 @@ if true then
end
addCheckBox("reUse", "Keep Crosshair", false, rightPanel)
addCheckBox("reUse", "Keep Crosshair", false, rightPanel, "Keep crosshair after using with item")
if true then
local excluded = {268, 237, 238, 23373, 266, 236, 239, 7643, 23375, 7642, 23374, 5908, 5942}
@ -388,7 +405,7 @@ if true then
end
addCheckBox("suppliesControl", "TargetBot off if low supply", false, leftPanel)
addCheckBox("suppliesControl", "TargetBot off if low supply", false, leftPanel, "Turn off TargetBot if either one of supply amount is below 50% of minimum.")
if true then
macro(500, function()
if not settings.suppliesControl then return end
@ -400,7 +417,7 @@ if true then
end)
end
addCheckBox("holdMwall", "Hold MW/WG", true, rightPanel)
addCheckBox("holdMwall", "Hold MW/WG", true, rightPanel, "Mark tiles with below hotkeys to automatically use Magic Wall or Wild Growth")
addTextEdit("holdMwHot", "Magic Wall Hotkey: ", "F5", rightPanel)
addTextEdit("holdWgHot", "Wild Growth Hotkey: ", "F6", rightPanel)
if true then
@ -496,7 +513,7 @@ if true then
end)
end
addCheckBox("checkPlayer", "Check Players", true, rightPanel)
addCheckBox("checkPlayer", "Check Players", true, rightPanel, "Auto look on players and mark level and vocation on character model")
if true then
local found
local function checkPlayers()
@ -561,8 +578,9 @@ if true then
end)
end
addCheckBox("title", "Open Next Loot Container", true, leftPanel)
addCheckBox("nextBackpack", "Open Next Loot Container", true, leftPanel, "Auto open next loot container if full - has to have the same ID.")
local function openNextLootContainer()
if not settings.nextBackpack then return end
local containers = getContainers()
local lootCotaniersIds = CaveBot.GetLootContainers()
@ -592,3 +610,23 @@ if true then
end)
end)
end
addCheckBox("highlightTarget", "Highlight Current Target", true, rightPanel, "Additionaly hightlight current target with red glow")
if true then
local function forceMarked(creature)
if target() == creature then
creature:setMarked("red")
return schedule(333, function() forceMarked(creature) end)
end
end
onAttackingCreatureChange(function(newCreature, oldCreature)
if not settings.highlightTarget then return end
if oldCreature then
oldCreature:setMarked('')
end
if newCreature then
forceMarked(newCreature)
end
end)
end

View File

@ -2,7 +2,7 @@ ExtrasScrollBar < Panel
height: 28
margin-top: 3
Label
UIWidget
id: text
anchors.left: parent.left
anchors.right: parent.right
@ -23,7 +23,7 @@ ExtrasTextEdit < Panel
height: 40
margin-top: 7
Label
UIWidget
id: text
anchors.left: parent.left
anchors.right: parent.right
@ -47,7 +47,7 @@ ExtrasItem < Panel
margin-left: 25
margin-right: 25
Label
UIWidget
id: text
anchors.left: parent.left
anchors.verticalCenter: next.verticalCenter

View File

@ -0,0 +1,30 @@
setDefaultTab("Tools")
local targetID = nil
-- escape when attacking will reset hold target
onKeyPress(function(keys)
if keys == "Escape" and targetID then
targetID = nil
end
end)
macro(100, "Hold Target", function()
-- if attacking then save it as target, but check pos z in case of marking by mistake on other floor
if target() and target():getPosition().z == posz() and not target():isNpc() then
targetID = target():getId()
elseif not target() then
-- there is no saved data, do nothing
if not targetID then return end
-- look for target
for i, spec in ipairs(getSpectators()) do
local sameFloor = spec:getPosition().z == posz()
local oldTarget = spec:getId() == targetID
if sameFloor and oldTarget then
attack(spec)
end
end
end
end)

View File

@ -1219,6 +1219,49 @@ LootItems = {
["zaoan sword"] = 30000,
["zaogun flag"] = 600,
["zaogun shoulderplates"] = 150,
-- 12.70
["carnisylvan bark"] = 230,
["carnisylvan finger"] = 250,
["human teeth"] = 2000,
["abomination's eye"] = 650000,
["abomination's tail"] = 700000,
["abomination's tongue"] = 950000,
["afflicted strider head"] = 900,
["afflicted strider worms"] = 500,
["bashmu fang"] = 600,
["bashmu feather"] = 350,
["bashmu tongue"] = 400,
["blemished spawn abdomen"] = 550,
["blemished spawn head"] = 800,
["blemished spawn tail"] = 1000,
["brainstealer's brain"] = 300000,
["brainstealer's brainwave"] = 440000,
["brainstealer's tissue"] = 240000,
["cave chimera head"] = 1200,
["cave chimera leg"] = 650,
["curl of hair"] = 320000,
["eyeless devourer legs"] = 650,
["eyeless devourer maw"] = 420,
["eyeless devourer tongue"] = 900,
["girtablilu warrior carapace"] = 520,
["lavafungus head"] = 900,
["lavafungus ring"] = 390,
["lavaworm jaws"] = 1100,
["lavaworm spike roots"] = 600,
["lavaworm spikes"] = 750,
["old girtablilu carapace"] = 570,
["old royal diary"] = 220000,
["scorpion charm"] = 620,
["tremendous tyrant head"] = 930,
["tremendous tyrant shell"] = 740,
["varnished diremaw brainpan"] = 750,
["varnished diremaw legs"] = 670,
["streaked devourer eyes"] = 500,
["streaked devourer legs"] = 600,
["streaked devourer maw"] = 400,
["eldritch crystal"] = 48000,
-- supplies
["mana potion"] = 56,
["strong mana potion"] = 93,

Some files were not shown because too many files have changed in this diff Show More