Updated to OTCv8 3.1 rev 229
BIN
data/images/game/actionbar/actionbarslot.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
data/images/game/actionbar/arrow-disabled.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/game/actionbar/arrow-skip-disabled.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/game/actionbar/arrow-skip.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/game/actionbar/arrow.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/game/actionbar/locked.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/game/actionbar/unlocked.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
data/images/ui/actionbar_background.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
@ -45,17 +45,17 @@ OptionPanel
|
||||
type: horizontalBox
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarBottom1
|
||||
id: actionbar1
|
||||
!text: tr('Bar 1')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarBottom2
|
||||
id: actionbar2
|
||||
!text: tr('Bar 2')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarBottom3
|
||||
id: actionbar3
|
||||
!text: tr('Bar 3')
|
||||
width: 60
|
||||
|
||||
@ -75,17 +75,17 @@ OptionPanel
|
||||
type: horizontalBox
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarLeft1
|
||||
id: actionbar4
|
||||
!text: tr('Bar 1')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarLeft2
|
||||
id: actionbar5
|
||||
!text: tr('Bar 2')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarLeft3
|
||||
id: actionbar6
|
||||
!text: tr('Bar 3')
|
||||
width: 60
|
||||
|
||||
@ -104,17 +104,17 @@ OptionPanel
|
||||
visible: false
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarRight1
|
||||
id: actionbar7
|
||||
!text: tr('Bar 1')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarRight2
|
||||
id: actionbar8
|
||||
!text: tr('Bar 2')
|
||||
width: 60
|
||||
|
||||
OptionCheckBox
|
||||
id: actionbarRight3
|
||||
id: actionbar9
|
||||
!text: tr('Bar 3')
|
||||
width: 60
|
||||
|
||||
|
@ -52,17 +52,15 @@ local defaultOptions = {
|
||||
|
||||
topBar = true,
|
||||
|
||||
actionbarBottom1 = true,
|
||||
actionbarBottom2 = false,
|
||||
actionbarBottom3 = false,
|
||||
|
||||
actionbarLeft1 = false,
|
||||
actionbarLeft2 = false,
|
||||
actionbarLeft3 = false,
|
||||
|
||||
actionbarRight1 = false,
|
||||
actionbarRight2 = false,
|
||||
actionbarRight3 = false,
|
||||
actionbar1 = true,
|
||||
actionbar2 = false,
|
||||
actionbar3 = false,
|
||||
actionbar4 = false,
|
||||
actionbar5 = false,
|
||||
actionbar6 = false,
|
||||
actionbar7 = false,
|
||||
actionbar8 = false,
|
||||
actionbar9 = false,
|
||||
|
||||
actionbarLock = false,
|
||||
|
||||
|
@ -156,6 +156,7 @@ function UIMiniWindow:setup()
|
||||
local parent = rootWidget:recursiveGetChildById(selfSettings.parentId)
|
||||
if parent then
|
||||
if parent:getClassName() == 'UIMiniWindowContainer' and selfSettings.index and parent:isOn() then
|
||||
self:setParent(parent, true)
|
||||
self.miniIndex = selfSettings.index
|
||||
parent:scheduleInsert(self, selfSettings.index)
|
||||
elseif selfSettings.position then
|
||||
|
@ -1,9 +1,7 @@
|
||||
Module
|
||||
name: game_actionbar
|
||||
description: Action bar
|
||||
author: otclient@otclient.ovh
|
||||
website: otclient.ovh
|
||||
author: https://github.com/Vithrax/
|
||||
sandboxed: true
|
||||
scripts: [ actionbar ]
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
||||
scripts: [ actionbar ]
|
@ -1,29 +1,42 @@
|
||||
ActionButton < Panel
|
||||
ActionButton < UIButton
|
||||
font: cipsoftFont
|
||||
width: 40
|
||||
padding: 1 1 1 1
|
||||
width: 36
|
||||
padding: 1
|
||||
margin-left: 1
|
||||
draggable: true
|
||||
|
||||
Item
|
||||
id: item
|
||||
anchors.fill: parent
|
||||
padding: 1
|
||||
&selectable: true
|
||||
&editable: false
|
||||
virtual: true
|
||||
border-width: 1
|
||||
|
||||
border-color: #00000000
|
||||
draggable: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbarslot
|
||||
image-source: /images/game/actionbar/actionbarslot
|
||||
image-color: #dfdfdf
|
||||
image-clip: 0 0 34 34
|
||||
image-border: 0
|
||||
|
||||
$on:
|
||||
image-source: /images/ui/button
|
||||
image-color: #dfdfdf
|
||||
image-clip: 0 0 22 23
|
||||
image-border: 3
|
||||
|
||||
$pressed on:
|
||||
image-clip: 0 46 22 23
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.fill: prev
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
phantom: true
|
||||
margin: 1
|
||||
text-align: center
|
||||
font: verdana-9px
|
||||
|
||||
@ -31,7 +44,7 @@ ActionButton < Panel
|
||||
id: hotkeyLabel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin: 2 3 3 3
|
||||
margin: 3 4 3 3
|
||||
text-auto-resize: true
|
||||
text-wrap: false
|
||||
phantom: true
|
||||
@ -39,22 +52,172 @@ ActionButton < Panel
|
||||
color: white
|
||||
background: #292A2A
|
||||
|
||||
Label
|
||||
id: parameterText
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: -3
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
font: verdana-9px
|
||||
color: white
|
||||
text-align: center
|
||||
|
||||
UIProgressRect
|
||||
id: cooldown
|
||||
background: #585858AA
|
||||
background: #101010aa
|
||||
percent: 100
|
||||
focusable: false
|
||||
phantom: true
|
||||
anchors.fill: parent
|
||||
margin: 1 1 1 1
|
||||
font: verdana-11px-rounded
|
||||
color: white
|
||||
|
||||
|
||||
LeftSliders < Panel
|
||||
size: 17 34
|
||||
|
||||
Button
|
||||
id: prev
|
||||
anchors.fill: parent
|
||||
anchors.bottom: parent.verticalCenter
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the previous action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow
|
||||
|
||||
Button
|
||||
id: first
|
||||
anchors.fill: parent
|
||||
anchors.top: parent.verticalCenter
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the first action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-skip-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow-skip
|
||||
|
||||
RightSliders < Panel
|
||||
size: 29 34
|
||||
|
||||
Button
|
||||
id: lock
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
width: 12
|
||||
@onClick: modules.game_actionbar.changeLockState(self)
|
||||
|
||||
$!on:
|
||||
tooltip: Action Bar Locked: You cannot assign actions to or switch actions on action buttons by "drag&drop".
|
||||
|
||||
$on:
|
||||
tooltip: Action Bar Unlocked: You can assign actions to or switch actions on action buttons by "drag&drop".
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
margin-right: 1
|
||||
phantom: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/locked
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/unlocked
|
||||
|
||||
Button
|
||||
id: next
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: lock.left
|
||||
margin-right: 1
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the next action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-top: 1
|
||||
margin-left: 2
|
||||
rotation: 180
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow
|
||||
|
||||
Button
|
||||
id: last
|
||||
anchors.top: parent.verticalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: prev.right
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the last action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-top: 1
|
||||
margin-left: 1
|
||||
rotation: 180
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-skip-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow-skip
|
||||
|
||||
Panel
|
||||
id: actionBar
|
||||
focusable: false
|
||||
image-source: /images/ui/panel_side
|
||||
image-border: 4
|
||||
image-source: /images/ui/actionbar_background
|
||||
image-border: 1
|
||||
margin-top: -1
|
||||
|
||||
$on:
|
||||
@ -65,77 +228,37 @@ Panel
|
||||
height: 0
|
||||
visible: false
|
||||
|
||||
TabButton
|
||||
id: prevButton
|
||||
icon: /images/game/console/leftarrow
|
||||
LeftSliders
|
||||
id: prevPanel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-left: 1
|
||||
margin-top: 1
|
||||
margin-bottom: 2
|
||||
|
||||
Panel
|
||||
ScrollablePanel
|
||||
id: tabBar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
anchors.right: next.left
|
||||
margin-right: 3
|
||||
anchors.right: nextPanel.left
|
||||
margin-left: 4
|
||||
margin-right: 4
|
||||
clipping: true
|
||||
padding-top: 2
|
||||
padding-bottom: 2
|
||||
horizontal-scrollbar: actionScroll
|
||||
layout: horizontalBox
|
||||
|
||||
TabButton
|
||||
id: nextButton
|
||||
icon: /images/game/console/rightarrow
|
||||
anchors.right: parent.right
|
||||
|
||||
HorizontalScrollBar
|
||||
id: actionScroll
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 1
|
||||
margin-top: 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
|
||||
step: 37
|
||||
pixels-scroll: true
|
||||
visible: false
|
||||
|
||||
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
|
||||
RightSliders
|
||||
id: nextPanel
|
||||
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()
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-right: 1
|
56
modules/game_actionbar/hotkey.otui
Normal file
@ -0,0 +1,56 @@
|
||||
MainWindow
|
||||
id: assignHotkeyWindow
|
||||
size: 400 170
|
||||
|
||||
FlatLabel
|
||||
id: display
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 33
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: desc
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
multi-line: true
|
||||
height: 40
|
||||
text-wrap: true
|
||||
text: Click "Ok" to assign the hotkey. Click "Clear" to remove the hotkey from "
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: buttonClose
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Close
|
||||
@onClick: self:getParent():destroy()
|
||||
|
||||
Button
|
||||
id: buttonClear
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Clear
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Ok
|
100
modules/game_actionbar/object.otui
Normal file
@ -0,0 +1,100 @@
|
||||
RoundCheckBox < CheckBox
|
||||
image-source: /images/ui/checkbox_round
|
||||
|
||||
$first:
|
||||
margin-top: 2
|
||||
|
||||
$!first:
|
||||
margin-top: 5
|
||||
|
||||
MainWindow
|
||||
id: assignItemWindow
|
||||
size: 275 195
|
||||
|
||||
UIItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
size: 86 86
|
||||
padding: 5
|
||||
&selectable: true
|
||||
&editable: false
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 1
|
||||
|
||||
Panel
|
||||
id: checks
|
||||
anchors.left: prev.right
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-left: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
RoundCheckBox
|
||||
id: useSelf
|
||||
text: Use on yourself
|
||||
enabled: false
|
||||
|
||||
RoundCheckBox
|
||||
id: useTarget
|
||||
text: Use on target
|
||||
enabled: false
|
||||
|
||||
RoundCheckBox
|
||||
id: useCross
|
||||
text: With crosshair
|
||||
enabled: false
|
||||
|
||||
RoundCheckBox
|
||||
id: equip
|
||||
text: Equip/Unequip
|
||||
enabled: false
|
||||
|
||||
RoundCheckBox
|
||||
id: use
|
||||
text: Use
|
||||
enabled: false
|
||||
|
||||
Button
|
||||
id: select
|
||||
anchors.left: item.left
|
||||
anchors.right: item.right
|
||||
anchors.top: item.bottom
|
||||
margin-top: 5
|
||||
font: cipsoftFont
|
||||
height: 20
|
||||
text: Select item
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: buttonClose
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Close
|
||||
|
||||
Button
|
||||
id: buttonApply
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Apply
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Ok
|
@ -1,30 +1,37 @@
|
||||
SideActionButton < Panel
|
||||
SideActionButton < UIButton
|
||||
font: cipsoftFont
|
||||
height: 40
|
||||
padding: 1 1 1 1
|
||||
|
||||
$first:
|
||||
margin-top: -4
|
||||
|
||||
$!first:
|
||||
margin-top: -1
|
||||
height: 36
|
||||
padding: 1
|
||||
margin-top: 1
|
||||
|
||||
Item
|
||||
id: item
|
||||
anchors.fill: parent
|
||||
padding: 1
|
||||
&selectable: true
|
||||
&editable: false
|
||||
virtual: true
|
||||
border-width: 1
|
||||
|
||||
border-color: #00000000
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbarslot
|
||||
image-source: /images/game/actionbar/actionbarslot
|
||||
image-color: #dfdfdf
|
||||
image-clip: 0 0 34 34
|
||||
image-border: 0
|
||||
|
||||
$on:
|
||||
image-source: /images/ui/button
|
||||
image-color: #dfdfdf
|
||||
image-clip: 0 0 22 23
|
||||
image-border: 3
|
||||
|
||||
$pressed on:
|
||||
image-clip: 0 46 22 23
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.fill: prev
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
phantom: true
|
||||
@ -35,7 +42,7 @@ SideActionButton < Panel
|
||||
id: hotkeyLabel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin: 2 3 3 3
|
||||
margin: 3 4 3 3
|
||||
text-auto-resize: true
|
||||
text-wrap: false
|
||||
phantom: true
|
||||
@ -43,103 +50,214 @@ SideActionButton < Panel
|
||||
color: white
|
||||
background: #292A2A
|
||||
|
||||
Label
|
||||
id: parameterText
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: -3
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
font: verdana-9px
|
||||
color: white
|
||||
text-align: center
|
||||
|
||||
UIProgressRect
|
||||
id: cooldown
|
||||
background: #585858AA
|
||||
background: #101010aa
|
||||
percent: 100
|
||||
focusable: false
|
||||
phantom: true
|
||||
anchors.fill: parent
|
||||
margin: 1 1 1 1
|
||||
font: verdana-11px-rounded
|
||||
color: white
|
||||
|
||||
|
||||
TopSliders < Panel
|
||||
size: 34 17
|
||||
|
||||
Button
|
||||
id: prev
|
||||
anchors.fill: parent
|
||||
anchors.right: parent.horizontalCenter
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the previous action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-left: 1
|
||||
rotation: 90
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow
|
||||
|
||||
Button
|
||||
id: first
|
||||
anchors.fill: parent
|
||||
anchors.left: parent.horizontalCenter
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the first action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-left: 1
|
||||
rotation: 90
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-skip-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow-skip
|
||||
|
||||
BottomSliders < Panel
|
||||
size: 34 32
|
||||
|
||||
Button
|
||||
id: lock
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 15
|
||||
@onClick: modules.game_actionbar.changeLockState(self)
|
||||
|
||||
$!on:
|
||||
tooltip: Action Bar Locked: You cannot assign actions to or switch actions on action buttons by "drag&drop".
|
||||
|
||||
$on:
|
||||
tooltip: Action Bar Unlocked: You can assign actions to or switch actions on action buttons by "drag&drop".
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-bottom: 1
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/locked
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/unlocked
|
||||
|
||||
Button
|
||||
id: next
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
height: 17
|
||||
margin-right: 1
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the next action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-top: 1
|
||||
rotation: 270
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow
|
||||
|
||||
Button
|
||||
id: last
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
height: 17
|
||||
@onClick: modules.game_actionbar.moveActionButtons(self)
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
tooltip: No further action buttons in this direction
|
||||
|
||||
$on:
|
||||
tooltip: Move to the last action button
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.centerIn: parent
|
||||
phantom: true
|
||||
margin-top: 1
|
||||
rotation: 270
|
||||
on: true
|
||||
|
||||
$!on:
|
||||
image-source: /images/game/actionbar/arrow-skip-disabled
|
||||
|
||||
$on:
|
||||
image-source: /images/game/actionbar/arrow-skip
|
||||
|
||||
Panel
|
||||
id: actionBar
|
||||
focusable: false
|
||||
image-source: /images/ui/panel_side
|
||||
image-border: 4
|
||||
margin-top: -2
|
||||
image-source: /images/ui/actionbar_background
|
||||
image-border: 1
|
||||
margin-top: -5
|
||||
|
||||
$on:
|
||||
width: 40
|
||||
width: 37
|
||||
visible: true
|
||||
|
||||
$!on:
|
||||
width: 0
|
||||
visible: false
|
||||
|
||||
TabButton
|
||||
id: prevButton
|
||||
icon: /images/game/console/uparrow
|
||||
anchors.left: parent.left
|
||||
TopSliders
|
||||
id: prevPanel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-top: -1
|
||||
margin-left: 1
|
||||
margin-right: 1
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 1
|
||||
|
||||
Panel
|
||||
ScrollablePanel
|
||||
id: tabBar
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: nextPanel.top
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: next.top
|
||||
margin-top: 3
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
margin-bottom: 4
|
||||
clipping: true
|
||||
padding-left: 1
|
||||
vertical-scrollbar: actionScroll
|
||||
layout: verticalBox
|
||||
|
||||
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
|
||||
VerticalScrollBar
|
||||
id: actionScroll
|
||||
anchors.top: parent.top
|
||||
text-auto-resize: true
|
||||
text-align: left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
step: 37
|
||||
pixels-scroll: true
|
||||
visible: false
|
||||
|
||||
Label
|
||||
id: comboPreview
|
||||
!text: tr('Current action hotkey: %s', 'none')
|
||||
BottomSliders
|
||||
id: nextPanel
|
||||
anchors.bottom: parent.bottom
|
||||
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()
|
||||
margin-bottom: 3
|
150
modules/game_actionbar/spell.otui
Normal file
@ -0,0 +1,150 @@
|
||||
SpellPreview < UICheckBox
|
||||
height: 34
|
||||
text-wrap: true
|
||||
multi-line: true
|
||||
focusable: true
|
||||
text-offset: 38 2
|
||||
image-source:
|
||||
change-cursor-image: false
|
||||
|
||||
$hover !disabled:
|
||||
color: #ffffff
|
||||
|
||||
$!checked:
|
||||
background-color: alpha
|
||||
|
||||
$checked:
|
||||
background-color: #ffffff22
|
||||
|
||||
$disabled:
|
||||
image-color: #dfdfdf88
|
||||
color: #dfdfdf88
|
||||
opacity: 0.8
|
||||
|
||||
UIWidget
|
||||
id: image
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
phantom: true
|
||||
padding: 1
|
||||
size: 34 34
|
||||
|
||||
MainWindow
|
||||
id: assignSpellWindow
|
||||
size: 275 310
|
||||
@onEscape: self:destroy()
|
||||
|
||||
SpellPreview
|
||||
id: preview
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
focusable: false
|
||||
|
||||
$!checked:
|
||||
background-color: alpha
|
||||
|
||||
$checked:
|
||||
background-color: alpha
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
TextList
|
||||
id: spellList
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
height: 120
|
||||
padding: 1
|
||||
focusable: false
|
||||
vertical-scrollbar: listScrollBar
|
||||
background-color: #484848
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: spellList.top
|
||||
anchors.right: spellList.right
|
||||
margin-right: 1
|
||||
anchors.bottom: spellList.bottom
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
FlatPanel
|
||||
id: checkPanel
|
||||
anchors.top: spellList.bottom
|
||||
margin-top: 8
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 20
|
||||
|
||||
CheckBox
|
||||
id: tick
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
text: Only show vocation spells
|
||||
checked: true
|
||||
|
||||
Label
|
||||
id: paramLabel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
text: Parameter:
|
||||
height: 20
|
||||
text-horizontal-auto-resize: true
|
||||
text-offset: 0 3
|
||||
on: false
|
||||
|
||||
$on:
|
||||
color: white
|
||||
|
||||
$!on:
|
||||
color: #c0c0c0
|
||||
|
||||
TextEdit
|
||||
id: paramText
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
enabled: false
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: buttonClose
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Close
|
||||
|
||||
Button
|
||||
id: buttonApply
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Apply
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Ok
|
66
modules/game_actionbar/text.otui
Normal file
@ -0,0 +1,66 @@
|
||||
MainWindow
|
||||
id: assignTextWindow
|
||||
size: 275 150
|
||||
text: Assign Text
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Text:
|
||||
text-horizontal-auto-resize: true
|
||||
|
||||
TextEdit
|
||||
id: text
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
|
||||
FlatPanel
|
||||
id: checkPanel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 20
|
||||
|
||||
CheckBox
|
||||
id: tick
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
text: Send automatically
|
||||
checked: true
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: buttonClose
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Close
|
||||
|
||||
Button
|
||||
id: buttonApply
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Apply
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
anchors.right: prev.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
font: cipsoftFont
|
||||
text: Ok
|
@ -497,9 +497,7 @@ function initCallbacks()
|
||||
onRemoveItem = botContainerRemoveItem,
|
||||
onGameEditText = botGameEditText,
|
||||
onSpellCooldown = botSpellCooldown,
|
||||
onSpellGroupCooldown = botGroupSpellCooldown,
|
||||
onQuestLog = botGameQuestLog,
|
||||
onQuestLine = botGameQuestLine
|
||||
onSpellGroupCooldown = botGroupSpellCooldown
|
||||
})
|
||||
|
||||
connect(Tile, {
|
||||
@ -563,9 +561,7 @@ function terminateCallbacks()
|
||||
onAttackingCreatureChange = botAttackingCreatureChange,
|
||||
onGameEditText = botGameEditText,
|
||||
onSpellCooldown = botSpellCooldown,
|
||||
onSpellGroupCooldown = botGroupSpellCooldown,
|
||||
onQuestLog = botGameQuestLog,
|
||||
onQuestLine = botGameQuestLine
|
||||
onSpellGroupCooldown = botGroupSpellCooldown
|
||||
})
|
||||
|
||||
disconnect(Tile, {
|
||||
@ -800,14 +796,4 @@ end
|
||||
function botInventoryChange(player, slot, item, oldItem)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onInventoryChange(player, slot, item, oldItem) end)
|
||||
end
|
||||
|
||||
function botGameQuestLog(quests)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onGameQuestLog(quests) end)
|
||||
end
|
||||
|
||||
function botGameQuestLine(quests)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onGameQuestLine(questId, questMissions) end)
|
||||
end
|
64
modules/game_bot/default_configs/vBot_4.8/_Loader.lua
Normal file
@ -0,0 +1,64 @@
|
||||
-- load all otui files, order doesn't matter
|
||||
local configName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
|
||||
local configFiles = g_resources.listDirectoryFiles("/bot/" .. configName .. "/vBot", true, false)
|
||||
for i, file in ipairs(configFiles) do
|
||||
local ext = file:split(".")
|
||||
if ext[#ext]:lower() == "ui" or ext[#ext]:lower() == "otui" then
|
||||
g_ui.importStyle(file)
|
||||
end
|
||||
end
|
||||
|
||||
local function loadScript(name)
|
||||
return dofile("/vBot/" .. name .. ".lua")
|
||||
end
|
||||
|
||||
-- here you can set manually order of scripts
|
||||
-- libraries should be loaded first
|
||||
local luaFiles = {
|
||||
"main",
|
||||
"items",
|
||||
"vlib",
|
||||
"new_cavebot_lib",
|
||||
"configs", -- do not change this and above
|
||||
"extras",
|
||||
"cavebot",
|
||||
"playerlist",
|
||||
"BotServer",
|
||||
"alarms",
|
||||
"Conditions",
|
||||
"Equipper",
|
||||
"pushmax",
|
||||
"combo",
|
||||
"HealBot",
|
||||
"new_healer",
|
||||
"AttackBot", -- last of major modules
|
||||
"ingame_editor",
|
||||
"Dropper",
|
||||
"Containers",
|
||||
"quiver_manager",
|
||||
"quiver_label",
|
||||
"tools",
|
||||
"antiRs",
|
||||
"depot_withdraw",
|
||||
"eat_food",
|
||||
"equip",
|
||||
"exeta",
|
||||
"analyzer",
|
||||
"spy_level",
|
||||
"supplies",
|
||||
"depositer_config",
|
||||
"npc_talk",
|
||||
"xeno_menu",
|
||||
"hold_target",
|
||||
"cavebot_control_panel"
|
||||
}
|
||||
|
||||
for i, file in ipairs(luaFiles) do
|
||||
loadScript(file)
|
||||
end
|
||||
|
||||
setDefaultTab("Main")
|
||||
UI.Separator()
|
||||
UI.Label("Private Scripts:")
|
||||
UI.Separator()
|
509
modules/game_bot/default_configs/vBot_4.8/cavebot/actions.lua
Normal file
@ -0,0 +1,509 @@
|
||||
CaveBot.Actions = {}
|
||||
vBot.lastLabel = ""
|
||||
local oldTibia = g_game.getClientVersion() < 960
|
||||
local nextTile = nil
|
||||
|
||||
local noPath = 0
|
||||
|
||||
-- antistuck f()
|
||||
local nextPos = nil -- creature
|
||||
local nextPosF = nil -- furniture
|
||||
local function modPos(dir)
|
||||
local y = 0
|
||||
local x = 0
|
||||
|
||||
if dir == 0 then
|
||||
y = -1
|
||||
elseif dir == 1 then
|
||||
x = 1
|
||||
elseif dir == 2 then
|
||||
y = 1
|
||||
elseif dir == 3 then
|
||||
x = -1
|
||||
elseif dir == 4 then
|
||||
y = -1
|
||||
x = 1
|
||||
elseif dir == 5 then
|
||||
y = 1
|
||||
x = 1
|
||||
elseif dir == 6 then
|
||||
y = 1
|
||||
x = -1
|
||||
elseif dir == 7 then
|
||||
y = -1
|
||||
x = -1
|
||||
end
|
||||
|
||||
return {x, y}
|
||||
end
|
||||
|
||||
-- stack-covered antystuck, in & out pz
|
||||
local lastMoved = now - 200
|
||||
onTextMessage(function(mode, text)
|
||||
if text ~= 'There is not enough room.' then return end
|
||||
if CaveBot.isOff() then return end
|
||||
|
||||
local tiles = getNearTiles(pos())
|
||||
|
||||
for i, tile in ipairs(tiles) do
|
||||
if not tile:hasCreature() and tile:isWalkable() and #tile:getItems() > 9 then
|
||||
local topThing = tile:getTopThing()
|
||||
if not isInPz() then
|
||||
return useWith(3197, tile:getTopThing()) -- disintegrate
|
||||
else
|
||||
if now < lastMoved + 200 then return end -- delay to prevent clogging
|
||||
local nearTiles = getNearTiles(tile:getPosition())
|
||||
for i, tile in ipairs(nearTiles) do
|
||||
local tpos = tile:getPosition()
|
||||
if pos() ~= tpos then
|
||||
if tile:isWalkable() then
|
||||
lastMoved = now
|
||||
return g_game.move(topThing, tpos) -- move item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local furnitureIgnore = { 2986 }
|
||||
local function breakFurniture(destPos)
|
||||
if isInPz() then return false end
|
||||
local candidate = {thing=nil, dist=100}
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local walkable = tile:isWalkable()
|
||||
local topThing = tile:getTopThing()
|
||||
local isWg = topThing and topThing:getId() == 2130
|
||||
if topThing and (isWg or not table.find(furnitureIgnore, topThing:getId()) and topThing:isItem()) then
|
||||
local moveable = not topThing:isNotMoveable()
|
||||
local tpos = tile:getPosition()
|
||||
local path = findPath(player:getPosition(), tpos, 7, { ignoreNonPathable = true, precision = 1 })
|
||||
|
||||
if path then
|
||||
if isWg or (not walkable and moveable) then
|
||||
local distance = getDistanceBetween(destPos, tpos)
|
||||
|
||||
if distance < candidate.dist then
|
||||
candidate = {thing=topThing, dist=distance}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local thing = candidate.thing
|
||||
if thing then
|
||||
useWith(3197, thing)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function pushPlayer(creature)
|
||||
local cpos = creature:getPosition()
|
||||
local tiles = getNearTiles(cpos)
|
||||
|
||||
for i, tile in ipairs(tiles) do
|
||||
local pos = tile:getPosition()
|
||||
local minimapColor = g_map.getMinimapColor(pos)
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
|
||||
if not stairs and tile:isWalkable() then
|
||||
g_game.move(creature, pos)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function pathfinder()
|
||||
if not storage.extras.pathfinding then return end
|
||||
if noPath < 10 then return end
|
||||
|
||||
if not CaveBot.gotoNextWaypointInRange() then
|
||||
if getConfigFromName and getConfigFromName() then
|
||||
local profile = CaveBot.getCurrentProfile()
|
||||
local config = getConfigFromName()
|
||||
local newProfile = profile == '#Unibase' and config or '#Unibase'
|
||||
|
||||
CaveBot.setCurrentProfile(newProfile)
|
||||
end
|
||||
end
|
||||
noPath = 0
|
||||
return true
|
||||
end
|
||||
|
||||
-- it adds an action widget to list
|
||||
CaveBot.addAction = function(action, value, focus)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return warn("Invalid cavebot action: " .. action)
|
||||
end
|
||||
if type(value) == 'number' then
|
||||
value = tostring(value)
|
||||
end
|
||||
local widget = UI.createWidget("CaveBotAction", CaveBot.actionList)
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
widget.onDoubleClick = function(cwidget) -- edit on double click
|
||||
if CaveBot.Editor then
|
||||
schedule(20, function() -- schedule to have correct focus
|
||||
CaveBot.Editor.edit(cwidget.action, cwidget.value, function(action, value)
|
||||
CaveBot.editAction(cwidget, action, value)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
if focus then
|
||||
widget:focus()
|
||||
CaveBot.actionList:ensureChildVisible(widget)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
-- it updates existing widget, you should call CaveBot.save() later
|
||||
CaveBot.editAction = function(widget, action, value)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return warn("Invalid cavebot action: " .. action)
|
||||
end
|
||||
|
||||
if not widget.action or not widget.value then
|
||||
return warn("Invalid cavebot action widget, has missing action or value")
|
||||
end
|
||||
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
--[[
|
||||
registerAction:
|
||||
action - string, color - string, callback = function(value, retries, prev)
|
||||
value is a string value of action, retries is number which will grow by 1 if return is "retry"
|
||||
prev is a true when previuos action was executed succesfully, false otherwise
|
||||
it must return true if executed correctly, false otherwise
|
||||
it can also return string "retry", then the function will be called again in 20 ms
|
||||
]]--
|
||||
CaveBot.registerAction = function(action, color, callback)
|
||||
action = action:lower()
|
||||
if CaveBot.Actions[action] then
|
||||
return warn("Duplicated acction: " .. action)
|
||||
end
|
||||
CaveBot.Actions[action] = {
|
||||
color=color,
|
||||
callback=callback
|
||||
}
|
||||
end
|
||||
|
||||
CaveBot.registerAction("label", "yellow", function(value, retries, prev)
|
||||
vBot.lastLabel = value
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("gotolabel", "#FFFF55", function(value, retries, prev)
|
||||
return CaveBot.gotoLabel(value)
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev)
|
||||
if retries == 0 then
|
||||
local data = string.split(value, ",")
|
||||
local val = tonumber(data[1]:trim())
|
||||
local random
|
||||
local final
|
||||
|
||||
|
||||
if #data == 2 then
|
||||
random = tonumber(data[2]:trim())
|
||||
end
|
||||
|
||||
if random then
|
||||
local diff = (val/100) * random
|
||||
local min = val - diff
|
||||
local max = val + diff
|
||||
final = math.random(min, max)
|
||||
end
|
||||
final = final or val
|
||||
|
||||
CaveBot.delay(final)
|
||||
return "retry"
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("follow", "#FF8400", function(value, retries, prev)
|
||||
local c = getCreatureByName(value)
|
||||
if not c then
|
||||
print("CaveBot[follow]: can't find creature to follow")
|
||||
return false
|
||||
end
|
||||
local cpos = c:getPosition()
|
||||
local pos = pos()
|
||||
if getDistanceBetween(cpos, pos) < 2 then
|
||||
g_game.cancelFollow()
|
||||
return true
|
||||
else
|
||||
follow(c)
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("function", "red", function(value, retries, prev)
|
||||
local prefix = "local retries = " .. retries .. "\nlocal prev = " .. tostring(prev) .. "\nlocal delay = CaveBot.delay\nlocal gotoLabel = CaveBot.gotoLabel\n"
|
||||
prefix = prefix .. "local macro = function() warn('Macros inside cavebot functions are not allowed') end\n"
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
prefix = prefix .. "local " .. extension .. " = CaveBot.Extensions." .. extension .. "\n"
|
||||
end
|
||||
local status, result = pcall(function()
|
||||
return assert(load(prefix .. value, "cavebot_function"))()
|
||||
end)
|
||||
if not status then
|
||||
warn("warn in cavebot function:\n" .. result)
|
||||
return false
|
||||
end
|
||||
return result
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)")
|
||||
if not pos[1] then
|
||||
warn("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
-- reset pathfinder
|
||||
nextPosF = nil
|
||||
nextPos = nil
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
if retries >= 5 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- tried 5 times, can't get there
|
||||
end
|
||||
else
|
||||
if retries >= 100 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- tried 100 times, can't get there
|
||||
end
|
||||
end
|
||||
|
||||
local precision = tonumber(pos[1][5])
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
local maxDist = storage.extras.gotoMaxDistance or 40
|
||||
|
||||
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local minimapColor = g_map.getMinimapColor(pos)
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
|
||||
if stairs then
|
||||
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
|
||||
noPath = 0
|
||||
return true -- already at position
|
||||
end
|
||||
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
|
||||
noPath = 0
|
||||
return true -- already at position
|
||||
end
|
||||
-- check if there's a path to that place, ignore creatures and fields
|
||||
local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
|
||||
if not path then
|
||||
if breakFurniture(pos, storage.extras.machete) then
|
||||
CaveBot.delay(1000)
|
||||
retries = 0
|
||||
return "retry"
|
||||
end
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- there's no way
|
||||
end
|
||||
|
||||
-- check if there's a path to destination but consider Creatures (attack only if trapped)
|
||||
local path2 = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1 })
|
||||
if not path2 then
|
||||
local foundMonster = false
|
||||
for i, dir in ipairs(path) do
|
||||
local dirs = modPos(dir)
|
||||
nextPos = nextPos or playerPos
|
||||
nextPos.x = nextPos.x + dirs[1]
|
||||
nextPos.y = nextPos.y + dirs[2]
|
||||
|
||||
local tile = g_map.getTile(nextPos)
|
||||
if tile then
|
||||
if tile:hasCreature() then
|
||||
local creature = tile:getCreatures()[1]
|
||||
local hppc = creature:getHealthPercent()
|
||||
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
|
||||
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
|
||||
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
|
||||
if path then
|
||||
foundMonster = true
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
if distanceFromPlayer(creature:getPosition()) > 3 then
|
||||
CaveBot.walkTo(creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
|
||||
else
|
||||
attack(creature)
|
||||
end
|
||||
end
|
||||
g_game.setChaseMode(1)
|
||||
CaveBot.delay(100)
|
||||
retries = 0 -- reset retries, we are trying to unclog the cavebot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not foundMonster then
|
||||
foundMonster = false
|
||||
return false -- no other way
|
||||
end
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, don't ignore fields
|
||||
if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, ignore fields
|
||||
if CaveBot.walkTo(pos, maxDist, { ignoreNonPathable = true, allowUnseen = true, allowOnlyVisibleTiles = false }) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if retries >= 3 then
|
||||
-- try to lower precision, find something close to final position
|
||||
local precison = retries - 1
|
||||
if stairs then
|
||||
precison = 0
|
||||
end
|
||||
if CaveBot.walkTo(pos, 50, { ignoreNonPathable = true, precision = precison, allowUnseen = true, allowOnlyVisibleTiles = false }) then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.Config.get("mapClick") and retries >= 5 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("skipBlocked") then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false
|
||||
end
|
||||
|
||||
-- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
CaveBot.walkTo(pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("use", "#FFB272", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
local itemid = tonumber(value)
|
||||
if not itemid then
|
||||
warn("Invalid cavebot use action value. It should be (x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
use(topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("usewith", "#EEB292", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
if not itemid then
|
||||
warn("Invalid cavebot usewith action value. It should be (itemid,x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
local itemid = tonumber(pos[1][2])
|
||||
pos = {x=tonumber(pos[1][3]), y=tonumber(pos[1][4]), z=tonumber(pos[1][5])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
usewith(itemid, topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("say", "#FF55FF", function(value, retries, prev)
|
||||
say(value)
|
||||
return true
|
||||
end)
|
||||
CaveBot.registerAction("npcsay", "#FF55FF", function(value, retries, prev)
|
||||
NPC.say(value)
|
||||
return true
|
||||
end)
|
92
modules/game_bot/default_configs/vBot_4.8/cavebot/bank.lua
Normal file
@ -0,0 +1,92 @@
|
||||
CaveBot.Extensions.Bank = {}
|
||||
|
||||
local balance = 0
|
||||
|
||||
CaveBot.Extensions.Bank.setup = function()
|
||||
CaveBot.registerAction("bank", "#db5a5a", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 300
|
||||
local amount = 0
|
||||
local actionType
|
||||
local npcName
|
||||
local transferName
|
||||
local balanceLeft
|
||||
if #data ~= 3 and #data ~= 2 and #data ~= 4 then
|
||||
warn("CaveBot[Bank]: incorrect value!")
|
||||
return false
|
||||
else
|
||||
actionType = data[1]:trim():lower()
|
||||
npcName = data[2]:trim()
|
||||
if #data == 3 then
|
||||
amount = tonumber(data[3]:trim())
|
||||
end
|
||||
if #data == 4 then
|
||||
transferName = data[3]:trim()
|
||||
balanceLeft = tonumber(data[4]:trim())
|
||||
end
|
||||
end
|
||||
|
||||
if actionType ~= "withdraw" and actionType ~= "deposit" and actionType ~= "transfer" then
|
||||
warn("CaveBot[Bank]: incorrect action type! should be withdraw/deposit/transfer, is: " .. actionType)
|
||||
return false
|
||||
elseif actionType == "withdraw" then
|
||||
local value = tonumber(amount)
|
||||
if not value then
|
||||
warn("CaveBot[Bank]: incorrect amount value! should be number, is: " .. amount)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Bank]: too many tries, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[Bank]: NPC not found, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if actionType == "deposit" then
|
||||
CaveBot.Conversation("hi", "deposit all", "yes")
|
||||
CaveBot.delay(storage.extras.talkDelay*3)
|
||||
return true
|
||||
elseif actionType == "withdraw" then
|
||||
CaveBot.Conversation("hi", "withdraw", value, "yes")
|
||||
CaveBot.delay(storage.extras.talkDelay*4)
|
||||
return true
|
||||
else
|
||||
-- first check balance
|
||||
CaveBot.Conversation("hi", "balance")
|
||||
schedule(5000, function()
|
||||
local amountToTransfer = balance - balanceLeft
|
||||
if amountToTransfer <= 0 then
|
||||
warn("CaveBot[Bank] Not enough gold to transfer! proceeding")
|
||||
return false
|
||||
end
|
||||
CaveBot.Conversation("hi", "transfer", amountToTransfer, transferName, "yes")
|
||||
warn("CaveBot[Bank] transferred "..amountToTransfer.." gold to: "..transferName)
|
||||
end)
|
||||
CaveBot.delay(storage.extras.talkDelay*11)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("bank", "bank", {
|
||||
value="action, NPC name",
|
||||
title="Banker",
|
||||
description="action type(withdraw/deposit/transfer), NPC name, (if withdraw: amount|if transfer: name, balance left)",
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if mode == 51 and text:find("Your account balance is") then
|
||||
balance = getFirstNumberInText(text)
|
||||
end
|
||||
end)
|
@ -0,0 +1,76 @@
|
||||
CaveBot.Extensions.BuySupplies = {}
|
||||
|
||||
CaveBot.Extensions.BuySupplies.setup = function()
|
||||
CaveBot.registerAction("BuySupplies", "#C300FF", function(value, retries)
|
||||
local possibleItems = {}
|
||||
|
||||
local val = string.split(value, ",")
|
||||
local waitVal
|
||||
if #val == 0 or #val > 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect BuySupplies value")
|
||||
return false
|
||||
elseif #val == 2 then
|
||||
waitVal = tonumber(val[2]:trim())
|
||||
end
|
||||
|
||||
local npcName = val[1]:trim()
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[BuySupplies]: NPC not found")
|
||||
return false
|
||||
end
|
||||
|
||||
if not waitVal and #val == 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect delay values!")
|
||||
elseif waitVal and #val == 2 then
|
||||
delay(waitVal)
|
||||
end
|
||||
|
||||
if retries > 50 then
|
||||
print("CaveBot[BuySupplies]: Too many tries, can't buy")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
CaveBot.OpenNpcTrade()
|
||||
CaveBot.delay(storage.extras.talkDelay*2)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- get items from npc
|
||||
local npcItems = NPC.getBuyItems()
|
||||
for i,v in pairs(npcItems) do
|
||||
table.insert(possibleItems, v.id)
|
||||
end
|
||||
|
||||
for id, values in pairs(Supplies.getItemsData()) do
|
||||
id = tonumber(id)
|
||||
if table.find(possibleItems, id) then
|
||||
local max = values.max
|
||||
local current = player:getItemsCount(id)
|
||||
local toBuy = max - current
|
||||
|
||||
if toBuy > 0 then
|
||||
toBuy = math.min(100, toBuy)
|
||||
|
||||
NPC.buy(id, math.min(100, toBuy))
|
||||
print("CaveBot[BuySupplies]: bought " .. toBuy .. "x " .. id)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("CaveBot[BuySupplies]: bought everything, proceeding")
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
|
||||
value="NPC name",
|
||||
title="Buy Supplies",
|
||||
description="NPC Name, delay(in ms, optional)",
|
||||
})
|
||||
end
|
447
modules/game_bot/default_configs/vBot_4.8/cavebot/cavebot.lua
Normal file
@ -0,0 +1,447 @@
|
||||
local cavebotMacro = nil
|
||||
local config = nil
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
local ui = UI.createWidget("CaveBotPanel")
|
||||
|
||||
ui.list = ui.listPanel.list -- shortcut
|
||||
CaveBot.actionList = ui.list
|
||||
|
||||
if CaveBot.Editor then
|
||||
CaveBot.Editor.setup()
|
||||
end
|
||||
if CaveBot.Config then
|
||||
CaveBot.Config.setup()
|
||||
end
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.setup then
|
||||
callbacks.setup()
|
||||
end
|
||||
end
|
||||
|
||||
-- main loop, controlled by config
|
||||
local actionRetries = 0
|
||||
local prevActionResult = true
|
||||
cavebotMacro = macro(20, function()
|
||||
if TargetBot and TargetBot.isActive() and not TargetBot.isCaveBotActionAllowed() then
|
||||
CaveBot.resetWalking()
|
||||
return -- target bot or looting is working, wait
|
||||
end
|
||||
|
||||
if CaveBot.doWalking() then
|
||||
return -- executing walking3
|
||||
end
|
||||
|
||||
local actions = ui.list:getChildCount()
|
||||
if actions == 0 then return end
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
if not currentAction then
|
||||
currentAction = ui.list:getFirstChild()
|
||||
end
|
||||
local action = CaveBot.Actions[currentAction.action]
|
||||
local value = currentAction.value
|
||||
local retry = false
|
||||
if action then
|
||||
local status, result = pcall(function()
|
||||
CaveBot.resetWalking()
|
||||
return action.callback(value, actionRetries, prevActionResult)
|
||||
end)
|
||||
if status then
|
||||
if result == "retry" then
|
||||
actionRetries = actionRetries + 1
|
||||
retry = true
|
||||
elseif type(result) == 'boolean' then
|
||||
actionRetries = 0
|
||||
prevActionResult = result
|
||||
else
|
||||
warn("Invalid return from cavebot action (" .. currentAction.action .. "), should be \"retry\", false or true, is: " .. tostring(result))
|
||||
end
|
||||
else
|
||||
warn("warn while executing cavebot action (" .. currentAction.action .. "):\n" .. result)
|
||||
end
|
||||
else
|
||||
warn("Invalid cavebot action: " .. currentAction.action)
|
||||
end
|
||||
|
||||
if retry then
|
||||
return
|
||||
end
|
||||
|
||||
if currentAction ~= ui.list:getFocusedChild() then
|
||||
-- focused child can change durring action, get it again and reset state
|
||||
currentAction = ui.list:getFocusedChild() or ui.list:getFirstChild()
|
||||
actionRetries = 0
|
||||
prevActionResult = true
|
||||
end
|
||||
local nextAction = ui.list:getChildIndex(currentAction) + 1
|
||||
if nextAction > actions then
|
||||
nextAction = 1
|
||||
end
|
||||
ui.list:focusChild(ui.list:getChildByIndex(nextAction))
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
local lastConfig = ""
|
||||
config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, enabled, data)
|
||||
if enabled and CaveBot.Recorder.isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
CaveBot.setOff()
|
||||
return
|
||||
end
|
||||
|
||||
local currentActionIndex = ui.list:getChildIndex(ui.list:getFocusedChild())
|
||||
ui.list:destroyChildren()
|
||||
if not data then return cavebotMacro.setOff() end
|
||||
|
||||
local cavebotConfig = nil
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == "table" and #v == 2 then
|
||||
if v[1] == "config" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
warn("warn while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
cavebotConfig = result
|
||||
end
|
||||
elseif v[1] == "extensions" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
warn("warn while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onConfigChange then
|
||||
callbacks.onConfigChange(name, enabled, result[extension])
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
CaveBot.addAction(v[1], v[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange(name, enabled, cavebotConfig)
|
||||
|
||||
actionRetries = 0
|
||||
CaveBot.resetWalking()
|
||||
prevActionResult = true
|
||||
cavebotMacro.setOn(enabled)
|
||||
cavebotMacro.delay = nil
|
||||
if lastConfig == name then
|
||||
-- restore focused child on the action list
|
||||
ui.list:focusChild(ui.list:getChildByIndex(currentActionIndex))
|
||||
end
|
||||
lastConfig = name
|
||||
end)
|
||||
|
||||
-- ui callbacks
|
||||
ui.showEditor.onClick = function()
|
||||
if not CaveBot.Editor then return end
|
||||
if ui.showEditor:isOn() then
|
||||
CaveBot.Editor.hide()
|
||||
ui.showEditor:setOn(false)
|
||||
else
|
||||
CaveBot.Editor.show()
|
||||
ui.showEditor:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
ui.showConfig.onClick = function()
|
||||
if not CaveBot.Config then return end
|
||||
if ui.showConfig:isOn() then
|
||||
CaveBot.Config.hide()
|
||||
ui.showConfig:setOn(false)
|
||||
else
|
||||
CaveBot.Config.show()
|
||||
ui.showConfig:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- public function, you can use them in your scripts
|
||||
CaveBot.isOn = function()
|
||||
return config.isOn()
|
||||
end
|
||||
|
||||
CaveBot.isOff = function()
|
||||
return config.isOff()
|
||||
end
|
||||
|
||||
CaveBot.setOn = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOff(true)
|
||||
end
|
||||
config.setOn()
|
||||
end
|
||||
|
||||
CaveBot.setOff = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOn(true)
|
||||
end
|
||||
config.setOff()
|
||||
end
|
||||
|
||||
CaveBot.getCurrentProfile = function()
|
||||
return storage._configs.cavebot_configs.selected
|
||||
end
|
||||
|
||||
CaveBot.lastReachedLabel = function()
|
||||
return vBot.lastLabel
|
||||
end
|
||||
|
||||
CaveBot.gotoNextWaypointInRange = function()
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
local actions = ui.list:getChildren()
|
||||
|
||||
-- start searching from current index
|
||||
for i, child in ipairs(actions) do
|
||||
if i > index 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
|
||||
local maxDist = storage.extras.gotoMaxDistance
|
||||
if distanceFromPlayer(pos) <= maxDist then
|
||||
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
|
||||
ui.list:focusChild(ui.list:getChildByIndex(i-1))
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if not found then damn go from start
|
||||
for i, child in ipairs(actions) do
|
||||
if i <= index 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
|
||||
local maxDist = storage.extras.gotoMaxDistance
|
||||
if distanceFromPlayer(pos) <= maxDist then
|
||||
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
|
||||
ui.list:focusChild(ui.list:getChildByIndex(i-1))
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- not found
|
||||
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()
|
||||
local actions = ui.list:getChildren()
|
||||
local index
|
||||
|
||||
-- find index of label
|
||||
for i, child in pairs(actions) do
|
||||
local name = child:getText():lower()
|
||||
if name == label then
|
||||
index = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- if there's no index then label was not found
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index - 1 < 1 then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index-i)
|
||||
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
|
||||
return ui.list:focusChild(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.getPreviousLabel = function()
|
||||
local actions = ui.list:getChildren()
|
||||
-- check if config is empty
|
||||
if #actions == 0 then return false end
|
||||
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
--check we made any progress in waypoints, if no focused or first then no point checking
|
||||
if not currentAction or currentAction == ui.list:getFirstChild() then return false end
|
||||
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
|
||||
-- if not index then something went wrong and there's no selected child
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index - i < 1 then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index-i)
|
||||
if child then
|
||||
if child.action == "label" then
|
||||
return child.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.getNextLabel = function()
|
||||
local actions = ui.list:getChildren()
|
||||
-- check if config is empty
|
||||
if #actions == 0 then return false end
|
||||
|
||||
local currentAction = ui.list:getFocusedChild() or ui.list:getFirstChild()
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
|
||||
-- if not index then something went wrong
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index + i > #actions then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index+i)
|
||||
if child then
|
||||
if child.action == "label" then
|
||||
return child.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local botConfigName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
CaveBot.setCurrentProfile = function(name)
|
||||
if not g_resources.fileExists("/bot/"..botConfigName.."/cavebot_configs/"..name..".cfg") then
|
||||
return warn("there is no cavebot profile with that name!")
|
||||
end
|
||||
CaveBot.setOff()
|
||||
storage._configs.cavebot_configs.selected = name
|
||||
CaveBot.setOn()
|
||||
end
|
||||
|
||||
CaveBot.delay = function(value)
|
||||
cavebotMacro.delay = math.max(cavebotMacro.delay or 0, now + value)
|
||||
end
|
||||
|
||||
CaveBot.gotoLabel = function(label)
|
||||
label = label:lower()
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
if child.action == "label" and child.value:lower() == label then
|
||||
ui.list:focusChild(child)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.save = function()
|
||||
local data = {}
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
table.insert(data, {child.action, child.value})
|
||||
end
|
||||
|
||||
if CaveBot.Config then
|
||||
table.insert(data, {"config", json.encode(CaveBot.Config.save())})
|
||||
end
|
||||
|
||||
local extension_data = {}
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onSave then
|
||||
local ext_data = callbacks.onSave()
|
||||
if type(ext_data) == "table" then
|
||||
extension_data[extension] = ext_data
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(data, {"extensions", json.encode(extension_data, 2)})
|
||||
config.save(data)
|
||||
end
|
||||
|
||||
CaveBotList = function()
|
||||
return ui.list
|
||||
end
|
@ -0,0 +1,58 @@
|
||||
CaveBotAction < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
|
||||
CaveBotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 2
|
||||
margin-bottom: 5
|
||||
|
||||
Panel
|
||||
id: listPanel
|
||||
height: 100
|
||||
margin-top: 2
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: listScrollbar
|
||||
margin-right: 15
|
||||
focusable: false
|
||||
auto-focus: first
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollbar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
pixels-scroll: true
|
||||
step: 10
|
||||
|
||||
BotSwitch
|
||||
id: showEditor
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide waypoints editor
|
||||
|
||||
$!on:
|
||||
text: Show waypoints editor
|
||||
|
||||
BotSwitch
|
||||
id: showConfig
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide config
|
||||
|
||||
$!on:
|
||||
text: Show config
|
128
modules/game_bot/default_configs/vBot_4.8/cavebot/clear_tile.lua
Normal file
@ -0,0 +1,128 @@
|
||||
CaveBot.Extensions.ClearTile = {}
|
||||
|
||||
CaveBot.Extensions.ClearTile.setup = function()
|
||||
CaveBot.registerAction("ClearTile", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local pos = {x=tonumber(data[1]), y=tonumber(data[2]), z=tonumber(data[3])}
|
||||
local doors = false
|
||||
local stand = false
|
||||
local pPos = player:getPosition()
|
||||
|
||||
|
||||
for i, value in ipairs(data) do
|
||||
value = value:lower():trim()
|
||||
if value == "stand" then
|
||||
stand = true
|
||||
elseif value == "doors" then
|
||||
doors = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not #pos == 3 then
|
||||
warn("CaveBot[ClearTile]: invalid value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 20 then
|
||||
print("CaveBot[ClearTile]: too many tries, can't clear it")
|
||||
return false -- tried 20 times, can't clear it
|
||||
end
|
||||
|
||||
if getDistanceBetween(player:getPosition(), pos) == 0 then
|
||||
print("CaveBot[ClearTile]: tile reached, proceeding")
|
||||
return true
|
||||
end
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
print("CaveBot[ClearTile]: can't find tile or tile is unreachable, skipping")
|
||||
return false
|
||||
end
|
||||
local tPos = tile:getPosition()
|
||||
|
||||
-- no items on tile and walkability means we are done
|
||||
if tile:isWalkable() and tile:getTopUseThing():isNotMoveable() and not tile:hasCreature() and not doors then
|
||||
if stand then
|
||||
if not CaveBot.MatchPosition(tPos, 0) then
|
||||
CaveBot.GoTo(tPos, 0)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[ClearTile]: tile clear, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if not CaveBot.MatchPosition(tPos, 3) then
|
||||
CaveBot.GoTo(tPos, 3)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if retries > 0 then
|
||||
delay(1100)
|
||||
end
|
||||
|
||||
-- monster
|
||||
if tile:hasCreature() then
|
||||
local c = tile:getCreatures()[1]
|
||||
if c:isMonster() then
|
||||
attack(c)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
-- moveable item
|
||||
local item = tile:getTopMoveThing()
|
||||
if item:isItem() then
|
||||
if item and not item:isNotMoveable() then
|
||||
print("CaveBot[ClearTile]: moving item... " .. item:getId().. " from tile")
|
||||
g_game.move(item, pPos, item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
-- player
|
||||
|
||||
-- push creature
|
||||
if tile:hasCreature() then
|
||||
local c = tile:getCreatures()[1]
|
||||
if c and c:isPlayer() then
|
||||
|
||||
local candidates = {}
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local tPos = tile:getPosition()
|
||||
if getDistanceBetween(c:getPosition(), tPos) == 1 and tPos ~= pPos and tile:isWalkable() then
|
||||
table.insert(candidates, tPos)
|
||||
end
|
||||
end
|
||||
|
||||
if #candidates == 0 then
|
||||
print("CaveBot[ClearTile]: can't find tile to push, cannot clear way, skipping")
|
||||
return false
|
||||
else
|
||||
print("CaveBot[ClearTile]: pushing player... " .. c:getName() .. " out of the way")
|
||||
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, 1)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- doors
|
||||
if doors then
|
||||
use(tile:getTopUseThing())
|
||||
return "retry"
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("cleartile", "clear tile", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="position of tile to clear",
|
||||
description="tile position (x,y,z), doors/stand - optional",
|
||||
multiline=false
|
||||
})
|
||||
end
|
111
modules/game_bot/default_configs/vBot_4.8/cavebot/config.lua
Normal file
@ -0,0 +1,111 @@
|
||||
-- config for bot
|
||||
CaveBot.Config = {}
|
||||
CaveBot.Config.values = {}
|
||||
CaveBot.Config.default_values = {}
|
||||
CaveBot.Config.value_setters = {}
|
||||
|
||||
CaveBot.Config.setup = function()
|
||||
CaveBot.Config.ui = UI.createWidget("CaveBotConfigPanel")
|
||||
local ui = CaveBot.Config.ui
|
||||
local add = CaveBot.Config.add
|
||||
|
||||
add("ping", "Server ping", 100)
|
||||
add("walkDelay", "Walk delay", 10)
|
||||
add("mapClick", "Use map click", false)
|
||||
add("mapClickDelay", "Map click delay", 100)
|
||||
add("ignoreFields", "Ignore fields", false)
|
||||
add("skipBlocked", "Skip blocked path", false)
|
||||
add("useDelay", "Delay after use", 400)
|
||||
end
|
||||
|
||||
CaveBot.Config.show = function()
|
||||
CaveBot.Config.ui:show()
|
||||
end
|
||||
|
||||
CaveBot.Config.hide = function()
|
||||
CaveBot.Config.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange = function(configName, isEnabled, configData)
|
||||
for k, v in pairs(CaveBot.Config.default_values) do
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
if not configData then return end
|
||||
for k, v in pairs(configData) do
|
||||
if CaveBot.Config.value_setters[k] then
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.save = function()
|
||||
return CaveBot.Config.values
|
||||
end
|
||||
|
||||
CaveBot.Config.add = function(id, title, defaultValue)
|
||||
if CaveBot.Config.values[id] then
|
||||
return warn("Duplicated config key: " .. id)
|
||||
end
|
||||
|
||||
local panel
|
||||
local setter -- sets value
|
||||
if type(defaultValue) == "number" then
|
||||
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
|
||||
panel:setId(id)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onTextChange = function(widget, newValue)
|
||||
newValue = tonumber(newValue)
|
||||
if newValue then
|
||||
CaveBot.Config.values[id] = newValue
|
||||
CaveBot.save()
|
||||
end
|
||||
end
|
||||
elseif type(defaultValue) == "boolean" then
|
||||
panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui)
|
||||
panel:setId(id)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onClick = function(widget)
|
||||
widget:setOn(not widget:isOn())
|
||||
CaveBot.Config.values[id] = widget:isOn()
|
||||
CaveBot.save()
|
||||
end
|
||||
else
|
||||
return warn("Invalid default value of config for key " .. id .. ", should be number or boolean")
|
||||
end
|
||||
|
||||
panel.title:setText(tr(title) .. ":")
|
||||
|
||||
CaveBot.Config.value_setters[id] = setter
|
||||
CaveBot.Config.values[id] = defaultValue
|
||||
CaveBot.Config.default_values[id] = defaultValue
|
||||
end
|
||||
|
||||
CaveBot.Config.get = function(id)
|
||||
if CaveBot.Config.values[id] == nil then
|
||||
return warn("Invalid CaveBot.Config.get, id: " .. id)
|
||||
end
|
||||
return CaveBot.Config.values[id]
|
||||
end
|
||||
|
||||
CaveBot.Config.set = function(id, value)
|
||||
local valueType = CaveBot.Config.get(id)
|
||||
local panel = CaveBot.Config.ui[id]
|
||||
|
||||
if valueType == 'boolean' then
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
CaveBot.save()
|
||||
else
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
CaveBot.save()
|
||||
end
|
||||
end
|
@ -0,0 +1,57 @@
|
||||
CaveBotConfigPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Config
|
||||
margin-top: 5
|
||||
|
||||
CaveBotConfigNumberValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
CaveBotConfigBooleanValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotSwitch
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
$on:
|
||||
text: On
|
||||
|
||||
$!on:
|
||||
text: Off
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
105
modules/game_bot/default_configs/vBot_4.8/cavebot/d_withdraw.lua
Normal file
@ -0,0 +1,105 @@
|
||||
CaveBot.Extensions.DWithdraw = {}
|
||||
|
||||
CaveBot.Extensions.DWithdraw.setup = function()
|
||||
CaveBot.registerAction("dpwithdraw", "#002FFF", function(value, retries)
|
||||
local capLimit
|
||||
local data = string.split(value, ",")
|
||||
if retries > 600 then
|
||||
print("CaveBot[DepotWithdraw]: actions limit reached, proceeding")
|
||||
return false
|
||||
end
|
||||
local destContainer
|
||||
local depotContainer
|
||||
delay(70)
|
||||
|
||||
-- input validation
|
||||
if not value or #data ~= 3 and #data ~= 4 then
|
||||
warn("CaveBot[DepotWithdraw]: incorrect value!")
|
||||
return false
|
||||
end
|
||||
local indexDp = tonumber(data[1]:trim())
|
||||
local destName = data[2]:trim():lower()
|
||||
local destId = tonumber(data[3]:trim())
|
||||
if #data == 4 then
|
||||
capLimit = tonumber(data[4]:trim())
|
||||
end
|
||||
|
||||
|
||||
-- cap check
|
||||
if freecap() < (capLimit or 200) then
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
|
||||
return false
|
||||
end
|
||||
|
||||
-- containers
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local cName = container:getName():lower()
|
||||
if destName == cName then
|
||||
destContainer = container
|
||||
elseif cName:find("depot box") then
|
||||
depotContainer = container
|
||||
end
|
||||
end
|
||||
|
||||
if not destContainer then
|
||||
print("CaveBot[DepotWithdraw]: container not found!")
|
||||
return false
|
||||
end
|
||||
|
||||
if containerIsFull(destContainer) then
|
||||
for i, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(item, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- stash validation
|
||||
if depotContainer and #depotContainer:getItems() == 0 then
|
||||
print("CaveBot[DepotWithdraw]: all items withdrawn")
|
||||
g_game.close(depotContainer)
|
||||
return true
|
||||
end
|
||||
|
||||
if containerIsFull(destContainer) then
|
||||
for i, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(foundNextContainer, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: loot containers full!")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.OpenDepotBox(indexDp) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
for i, container in pairs(g_game.getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
for j, item in ipairs(container:getItems()) do
|
||||
statusMessage("[D_Withdraw] witdhrawing item: "..item:getId())
|
||||
g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("dpwithdraw", "dpwithdraw", {
|
||||
value="1, shopping bag, 21411",
|
||||
title="Loot Withdraw",
|
||||
description="insert index, destination container name and it's ID",
|
||||
})
|
||||
end
|
138
modules/game_bot/default_configs/vBot_4.8/cavebot/depositor.lua
Normal file
@ -0,0 +1,138 @@
|
||||
CaveBot.Extensions.Depositor = {}
|
||||
|
||||
--local variables
|
||||
local destination = nil
|
||||
local lootTable = nil
|
||||
local reopenedContainers = false
|
||||
|
||||
local function resetCache()
|
||||
reopenedContainers = false
|
||||
destination = nil
|
||||
lootTable = nil
|
||||
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
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"
|
||||
|
||||
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
|
||||
|
||||
-- loot list check
|
||||
lootTable = lootTable or CaveBot.GetLootItems()
|
||||
if #lootTable == 0 then
|
||||
print("CaveBot[Depositor]: no items in loot list. Wrong TargetBot Config? Proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
|
||||
delay(70)
|
||||
|
||||
-- backpacks etc
|
||||
if value:lower() == "yes" then
|
||||
if not reopenedContainers then
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
reopenedContainers = true
|
||||
return "retry"
|
||||
end
|
||||
-- open next backpacks if no more loot
|
||||
if not CaveBot.HasLootItems() then
|
||||
local lootContainers = CaveBot.GetLootContainers()
|
||||
for _, container in ipairs(getContainers()) do
|
||||
local cId = container:getContainerItem():getId()
|
||||
if table.find(lootContainers, cId) then
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:getId() == cId then
|
||||
g_game.open(item, container)
|
||||
delay(100)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- couldn't find next container, so we done
|
||||
print("CaveBot[Depositor]: all items stashed, no backpack to open next, proceeding")
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- first check items
|
||||
if retries == 0 then
|
||||
if not CaveBot.HasLootItems() then -- resource consuming function
|
||||
print("CaveBot[Depositor]: no items to stash, proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- next check retries
|
||||
if retries > 400 then
|
||||
print("CaveBot[Depositor]: Depositor actions limit reached, proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
|
||||
-- reaching and opening depot
|
||||
if not CaveBot.ReachAndOpenDepot() then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- add delay to prevent bugging
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
-- prep time and stashing
|
||||
destination = destination or getContainerByName("Depot chest")
|
||||
if not destination then return "retry" end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
local name = container:getName():lower()
|
||||
if not name:find("depot") and not name:find("your inbox") then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(lootTable, id) then
|
||||
local index = getStashingIndex(id) or item:isStackable() and 1 or 0
|
||||
statusMessage("[Depositer] stashing item: " ..id.. " to depot: "..index+1)
|
||||
CaveBot.StashItem(item, index, destination)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we gucci
|
||||
resetCache()
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("depositor", "depositor", {
|
||||
value="no",
|
||||
title="Depositor",
|
||||
description=description,
|
||||
validation="(yes|Yes|YES|no|No|NO)"
|
||||
})
|
||||
end
|
58
modules/game_bot/default_configs/vBot_4.8/cavebot/doors.lua
Normal file
@ -0,0 +1,58 @@
|
||||
CaveBot.Extensions.OpenDoors = {}
|
||||
|
||||
CaveBot.Extensions.OpenDoors.setup = function()
|
||||
CaveBot.registerAction("OpenDoors", "#00FFFF", function(value, retries)
|
||||
local pos = string.split(value, ",")
|
||||
local key = nil
|
||||
if #pos == 4 then
|
||||
key = tonumber(pos[4])
|
||||
end
|
||||
if not pos[1] then
|
||||
warn("CaveBot[OpenDoors]: invalid value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 5 then
|
||||
print("CaveBot[OpenDoors]: too many tries, can't open doors")
|
||||
return false -- tried 5 times, can't open
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1]), y=tonumber(pos[2]), z=tonumber(pos[3])}
|
||||
|
||||
local doorTile
|
||||
if not doorTile then
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if tile:getPosition().x == pos.x and tile:getPosition().y == pos.y and tile:getPosition().z == pos.z then
|
||||
doorTile = tile
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not doorTile then
|
||||
return false
|
||||
end
|
||||
|
||||
if not doorTile:isWalkable() then
|
||||
if not key then
|
||||
use(doorTile:getTopUseThing())
|
||||
delay(200)
|
||||
return "retry"
|
||||
else
|
||||
useWith(key, doorTile:getTopUseThing())
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
else
|
||||
print("CaveBot[OpenDoors]: possible to cross, proceeding")
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("opendoors", "open doors", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
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
|
186
modules/game_bot/default_configs/vBot_4.8/cavebot/editor.lua
Normal file
@ -0,0 +1,186 @@
|
||||
CaveBot.Editor = {}
|
||||
CaveBot.Editor.Actions = {}
|
||||
|
||||
-- also works as registerAction(action, params), then text == action
|
||||
-- params are options for text editor or function to be executed when clicked
|
||||
-- you have many examples how to use it bellow
|
||||
CaveBot.Editor.registerAction = function(action, text, params)
|
||||
if type(text) ~= 'string' then
|
||||
params = text
|
||||
text = action
|
||||
end
|
||||
|
||||
local color = nil
|
||||
if type(params) ~= 'function' then
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return warn("CaveBot editor warn: action " .. action .. " doesn't exist")
|
||||
end
|
||||
CaveBot.Editor.Actions[action] = params
|
||||
color = raction.color
|
||||
end
|
||||
|
||||
local button = UI.createWidget('CaveBotEditorButton', CaveBot.Editor.ui.buttons)
|
||||
button:setText(text)
|
||||
if color then
|
||||
button:setColor(color)
|
||||
end
|
||||
button.onClick = function()
|
||||
if type(params) == 'function' then
|
||||
params()
|
||||
return
|
||||
end
|
||||
CaveBot.Editor.edit(action, nil, function(action, value)
|
||||
local focusedAction = CaveBot.actionList:getFocusedChild()
|
||||
local index = CaveBot.actionList:getChildCount()
|
||||
if focusedAction then
|
||||
index = CaveBot.actionList:getChildIndex(focusedAction)
|
||||
end
|
||||
local widget = CaveBot.addAction(action, value)
|
||||
CaveBot.actionList:moveChildToIndex(widget, index + 1)
|
||||
CaveBot.actionList:focusChild(widget)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end
|
||||
return button
|
||||
end
|
||||
|
||||
CaveBot.Editor.setup = function()
|
||||
CaveBot.Editor.ui = UI.createWidget("CaveBotEditorPanel")
|
||||
local ui = CaveBot.Editor.ui
|
||||
local registerAction = CaveBot.Editor.registerAction
|
||||
|
||||
registerAction("move up", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index < 2 then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index - 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("edit", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action or not action.onDoubleClick then return end
|
||||
action.onDoubleClick(action)
|
||||
end)
|
||||
registerAction("move down", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index >= CaveBot.actionList:getChildCount() then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index + 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("remove", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
action:destroy()
|
||||
CaveBot.save()
|
||||
end)
|
||||
|
||||
registerAction("label", {
|
||||
value="labelName",
|
||||
title="Label",
|
||||
description="Add label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("delay", {
|
||||
value="500",
|
||||
title="Delay",
|
||||
description="Delay next action (in milliseconds),randomness (in percent-optional)",
|
||||
multiline=false,
|
||||
validation="^[0-9]{1,10}$|^[0-9]{1,10},[0-9]{1,4}$"
|
||||
})
|
||||
registerAction("gotolabel", "go to label", {
|
||||
value="labelName",
|
||||
title="Go to label",
|
||||
description="Go to label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("goto", "go to", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Go to position",
|
||||
description="Go to position (x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)$"
|
||||
})
|
||||
registerAction("use", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use",
|
||||
description="Use item from position (x,y,z) or from inventory (itemId)",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("usewith", "use with", {
|
||||
value=function() return "itemId," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use with",
|
||||
description="Use item at position (itemid,x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)$"
|
||||
})
|
||||
registerAction("say", {
|
||||
value="text",
|
||||
title="Say",
|
||||
description="Enter text to say",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("follow", {
|
||||
value="NPC name",
|
||||
title="Follow Creature",
|
||||
description="insert creature name to follow",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("npcsay", {
|
||||
value="text",
|
||||
title="NPC Say",
|
||||
description="Enter text to NPC say",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("function", {
|
||||
title="Edit bot function",
|
||||
multiline=true,
|
||||
value=CaveBot.Editor.ExampleFunctions[1][2],
|
||||
examples=CaveBot.Editor.ExampleFunctions,
|
||||
width=650
|
||||
})
|
||||
|
||||
ui.autoRecording.onClick = function()
|
||||
if ui.autoRecording:isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
else
|
||||
CaveBot.Recorder.enable()
|
||||
end
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
onPlayerPositionChange(function(pos)
|
||||
ui.pos:setText("Position: " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
|
||||
end)
|
||||
ui.pos:setText("Position: " .. posx() .. ", " .. posy() .. ", " .. posz())
|
||||
end
|
||||
|
||||
CaveBot.Editor.show = function()
|
||||
CaveBot.Editor.ui:show()
|
||||
end
|
||||
|
||||
|
||||
CaveBot.Editor.hide = function()
|
||||
CaveBot.Editor.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Editor.edit = function(action, value, callback) -- callback = function(action, value)
|
||||
local params = CaveBot.Editor.Actions[action]
|
||||
if not params then return end
|
||||
if not value then
|
||||
if type(params.value) == 'function' then
|
||||
value = params.value()
|
||||
elseif type(params.value) == 'string' then
|
||||
value = params.value
|
||||
end
|
||||
end
|
||||
|
||||
UI.EditorWindow(value, params, function(newText)
|
||||
callback(action, newText)
|
||||
end)
|
||||
end
|
@ -0,0 +1,44 @@
|
||||
CaveBotEditorButton < Button
|
||||
|
||||
|
||||
CaveBotEditorPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
id: pos
|
||||
text-align: center
|
||||
text: -
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 86 20
|
||||
cell-spacing: 1
|
||||
flow: true
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
text: Double click on action from action list to edit it
|
||||
text-align: center
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
margin-top: 3
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
|
||||
BotSwitch
|
||||
id: autoRecording
|
||||
text: Auto Recording
|
||||
margin-top: 3
|
||||
|
||||
BotButton
|
||||
margin-top: 3
|
||||
margin-bottom: 3
|
||||
text: Documentation
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")
|
@ -0,0 +1,114 @@
|
||||
CaveBot.Editor.ExampleFunctions = {}
|
||||
|
||||
local function addExampleFunction(title, text)
|
||||
return table.insert(CaveBot.Editor.ExampleFunctions, {title, text:trim()})
|
||||
end
|
||||
|
||||
addExampleFunction("Click to browse example functions", [[
|
||||
-- available functions/variables:
|
||||
-- prev - result of previous action (true or false)
|
||||
-- retries - number of retries of current function, goes up by one when you return "retry"
|
||||
-- delay(number) - delays bot next action, value in milliseconds
|
||||
-- gotoLabel(string) - goes to specific label, return true if label exists
|
||||
-- you can easily access bot extensions, Depositer.run() instead of CaveBot.Extensions.Depositer.run()
|
||||
-- also you can access bot global variables, like CaveBot, TargetBot
|
||||
-- use storage variable to store date between calls
|
||||
|
||||
-- function should return false, true or "retry"
|
||||
-- if "retry" is returned, function will be executed again in 20 ms (so better call delay before)
|
||||
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Check for PZ and wait until dropped", [[
|
||||
if retries > 25 or not isPzLocked() then
|
||||
return true
|
||||
else
|
||||
if isPoisioned() then
|
||||
say("exana pox")
|
||||
end
|
||||
if isPzLocked() then
|
||||
delay(8000)
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
]])
|
||||
|
||||
addExampleFunction("Check for stamina and imbues", [[
|
||||
if stamina() < 900 or player:getSkillLevel(11) == 0 then CaveBot.setOff() return false else return true end
|
||||
]])
|
||||
|
||||
addExampleFunction("buy 200 mana potion from npc Eryn", [[
|
||||
--buy 200 mana potions
|
||||
local npc = getCreatureByName("Eryn")
|
||||
if not npc then
|
||||
return false
|
||||
end
|
||||
if retries > 10 then
|
||||
return false
|
||||
end
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, {precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
NPC.say("trade")
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
NPC.buy(268, 100)
|
||||
schedule(1000, function()
|
||||
-- buy again in 1s
|
||||
NPC.buy(268, 100)
|
||||
NPC.closeTrade()
|
||||
NPC.say("bye")
|
||||
end)
|
||||
delay(1200)
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Say hello 5 times with some delay", [[
|
||||
--say hello
|
||||
if retries > 5 then
|
||||
return true -- finish
|
||||
end
|
||||
say("hello")
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot", [[
|
||||
TargetBot.setOff()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot", [[
|
||||
TargetBot.setOn()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot luring", [[
|
||||
TargetBot.enableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot luring", [[
|
||||
TargetBot.disableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Logout", [[
|
||||
g_game.safeLogout()
|
||||
delay(1000)
|
||||
return "retry"
|
||||
]])
|
||||
|
||||
addExampleFunction("Close Loot Containers", [[
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
return true
|
||||
]])
|
@ -0,0 +1,58 @@
|
||||
-- example cavebot extension (remember to add this file to ../cavebot.lua)
|
||||
CaveBot.Extensions.Example = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- setup is called automaticly when cavebot is ready
|
||||
CaveBot.Extensions.Example.setup = function()
|
||||
ui = UI.createWidget('BotTextEdit')
|
||||
ui:setText("Hello")
|
||||
ui.onTextChange = function()
|
||||
CaveBot.save() -- save new config when you change something
|
||||
end
|
||||
|
||||
-- add custom cavebot action (check out actions.lua)
|
||||
CaveBot.registerAction("sayhello", "orange", function(value, retries, prev)
|
||||
local how_many_times = tonumber(value)
|
||||
if retries >= how_many_times then
|
||||
return true
|
||||
end
|
||||
say("hello " .. (retries + 1))
|
||||
delay(250)
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
-- add this custom action to editor (check out editor.lua)
|
||||
CaveBot.Editor.registerAction("sayhello", "say hello", {
|
||||
value="5",
|
||||
title="Say hello",
|
||||
description="Says hello x times",
|
||||
validation="[0-9]{1,5}" -- regex, optional
|
||||
})
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can also be nil
|
||||
CaveBot.Extensions.Example.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
if configData["text"] then
|
||||
ui:setText(configData["text"])
|
||||
end
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config (so when CaveBot.save() is called), should return table or nil
|
||||
CaveBot.Extensions.Example.onSave = function()
|
||||
return {text=ui:getText()}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions to be used in cavebot function action
|
||||
-- an example: return Example.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua and example_functions.lua to learn more
|
||||
CaveBot.Extensions.Example.run = function(retries, prev)
|
||||
-- it will say text 10 times with some delay and then continue
|
||||
if retries > 10 then
|
||||
return true
|
||||
end
|
||||
say(ui:getText() .. " x" .. retries)
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
end
|
119
modules/game_bot/default_configs/vBot_4.8/cavebot/imbuing.lua
Normal file
@ -0,0 +1,119 @@
|
||||
-- imbuing window should be handled separatly
|
||||
-- reequiping should be handled separatly (ie. equipment manager)
|
||||
|
||||
CaveBot.Extensions.Imbuing = {}
|
||||
|
||||
local SHRINES = {25060, 25061, 25182, 25183}
|
||||
local currentIndex = 1
|
||||
local shrine = nil
|
||||
local item = nil
|
||||
local currentId = 0
|
||||
local triedToTakeOff = false
|
||||
local destination = nil
|
||||
|
||||
local function reset()
|
||||
EquipManager.setOn()
|
||||
shrine = nil
|
||||
currentIndex = 1
|
||||
item = nil
|
||||
currentId = 0
|
||||
triedToTakeOff = false
|
||||
destination = nil
|
||||
end
|
||||
|
||||
CaveBot.Extensions.Imbuing.setup = function()
|
||||
CaveBot.registerAction("imbuing", "red", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local ids = {}
|
||||
|
||||
if #data == 0 and value ~= 'name' then
|
||||
warn("CaveBot[Imbuing] no items added, proceeding")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
|
||||
-- setting of equipment manager so it wont disturb imbuing process
|
||||
EquipManager.setOff()
|
||||
|
||||
if value == 'name' then
|
||||
local imbuData = AutoImbueTable[player:getName()]
|
||||
for id, imbues in pairs(imbuData) do
|
||||
table.insert(ids, id)
|
||||
end
|
||||
else
|
||||
-- convert to number
|
||||
for i, id in ipairs(data) do
|
||||
id = tonumber(id)
|
||||
if not table.find(ids, id) then
|
||||
table.insert(ids, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- all items imbued, can proceed
|
||||
if currentIndex > #ids then
|
||||
warn("CaveBot[Imbuing] used shrine on all items, proceeding")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
for _, item in ipairs(tile:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(SHRINES, id) then
|
||||
shrine = item
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if not shrine
|
||||
if not shrine then
|
||||
warn("CaveBot[Imbuing] shrine not found! proceeding")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
|
||||
destination = shrine:getPosition()
|
||||
|
||||
currentId = ids[currentIndex]
|
||||
item = findItem(currentId)
|
||||
|
||||
-- maybe equipped? try to take off
|
||||
if not item then
|
||||
-- did try before, still not found so item is unavailable
|
||||
if triedToTakeOff then
|
||||
warn("CaveBot[Imbuing] item not found! skipping: "..currentId)
|
||||
triedToTakeOff = false
|
||||
currentIndex = currentIndex + 1
|
||||
return "retry"
|
||||
end
|
||||
triedToTakeOff = true
|
||||
g_game.equipItemId(currentId)
|
||||
delay(1000)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- we are past unequiping so just in case we were forced before, reset var
|
||||
triedToTakeOff = false
|
||||
|
||||
-- reaching shrine
|
||||
if not CaveBot.MatchPosition(destination, 1) then
|
||||
CaveBot.GoTo(destination, 1)
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
useWith(shrine, item)
|
||||
currentIndex = currentIndex + 1
|
||||
warn("CaveBot[Imbuing] Using shrine on item: "..currentId)
|
||||
delay(4000)
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("imbuing", "imbuing", {
|
||||
value="name",
|
||||
title="Auto Imbuing",
|
||||
description="insert below item ids to be imbued, separated by comma\nor 'name' to load from file",
|
||||
})
|
||||
end
|
@ -0,0 +1,91 @@
|
||||
CaveBot.Extensions.InWithdraw = {}
|
||||
|
||||
CaveBot.Extensions.InWithdraw.setup = function()
|
||||
CaveBot.registerAction("inwithdraw", "#002FFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local withdrawId
|
||||
local amount
|
||||
|
||||
-- validation
|
||||
if #data ~= 2 then
|
||||
warn("CaveBot[InboxWithdraw]: incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
withdrawId = tonumber(data[1])
|
||||
amount = tonumber(data[2])
|
||||
end
|
||||
|
||||
local currentAmount = itemAmount(withdrawId)
|
||||
|
||||
if currentAmount >= amount then
|
||||
print("CaveBot[InboxWithdraw]: enough items, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
print("CaveBot[InboxWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
-- actions
|
||||
local inboxContainer = getContainerByName("your inbox")
|
||||
delay(100)
|
||||
if not inboxContainer then
|
||||
if not CaveBot.ReachAndOpenInbox() then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
local inboxAmount = 0
|
||||
if not inboxContainer then
|
||||
return "retry"
|
||||
end
|
||||
for i, item in pairs(inboxContainer:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
inboxAmount = inboxAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
if inboxAmount == 0 then
|
||||
warn("CaveBot[InboxWithdraw]: not enough items in inbox container, proceeding")
|
||||
g_game.close(inboxContainer)
|
||||
return true
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "quiver") and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
|
||||
if not destination then
|
||||
print("CaveBot[InboxWithdraw]: couldn't find proper destination container, skipping")
|
||||
g_game.close(inboxContainer)
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
if item:isStackable() then
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(item:getCount(), (amount - currentAmount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("inwithdraw", "in withdraw", {
|
||||
value="id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert item id and amount",
|
||||
})
|
||||
end
|
29
modules/game_bot/default_configs/vBot_4.8/cavebot/lure.lua
Normal file
@ -0,0 +1,29 @@
|
||||
CaveBot.Extensions.Lure = {}
|
||||
|
||||
CaveBot.Extensions.Lure.setup = function()
|
||||
CaveBot.registerAction("lure", "#FF0090", function(value, retries)
|
||||
value = value:lower()
|
||||
if value == "start" then
|
||||
TargetBot.setOff()
|
||||
elseif value == "stop" then
|
||||
TargetBot.setOn()
|
||||
elseif value == "toggle" then
|
||||
if TargetBot.isOn() then
|
||||
TargetBot.setOff()
|
||||
else
|
||||
TargetBot.setOn()
|
||||
end
|
||||
else
|
||||
warn("incorrect lure value!")
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("lure", "lure", {
|
||||
value="toggle",
|
||||
title="Lure",
|
||||
description="TargetBot: start, stop, toggle",
|
||||
multiline=false,
|
||||
validation=[[(start|stop|toggle)$]]
|
||||
})
|
||||
end
|
@ -0,0 +1,26 @@
|
||||
local minimap = modules.game_minimap.minimapWidget
|
||||
|
||||
minimap.onMouseRelease = function(widget,pos,button)
|
||||
if not minimap.allowNextRelease then return true end
|
||||
minimap.allowNextRelease = false
|
||||
|
||||
local mapPos = minimap:getTilePosition(pos)
|
||||
if not mapPos then return end
|
||||
|
||||
if button == 1 then
|
||||
local player = g_game.getLocalPlayer()
|
||||
if minimap.autowalk then
|
||||
player:autoWalk(mapPos)
|
||||
end
|
||||
return true
|
||||
elseif button == 2 then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("minimapMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption(tr('Create mark'), function() minimap:createFlagWindow(mapPos) end)
|
||||
menu:addOption(tr('Add CaveBot GoTo'), function() CaveBot.addAction("goto", mapPos.x .. "," .. mapPos.y .. "," .. mapPos.z, true) CaveBot.save() end)
|
||||
menu:display(pos)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
@ -0,0 +1,47 @@
|
||||
CaveBot.Extensions.PosCheck = {}
|
||||
|
||||
local posCheckRetries = 0
|
||||
CaveBot.Extensions.PosCheck.setup = function()
|
||||
CaveBot.registerAction("PosCheck", "#00FFFF", function(value, retries)
|
||||
local tilePos
|
||||
local data = string.split(value, ",")
|
||||
if #data ~= 5 then
|
||||
warn("wrong travel format, should be: label, distance, x, y, z")
|
||||
return false
|
||||
end
|
||||
|
||||
local tilePos = player:getPosition()
|
||||
|
||||
tilePos.x = tonumber(data[3])
|
||||
tilePos.y = tonumber(data[4])
|
||||
tilePos.z = tonumber(data[5])
|
||||
|
||||
if posCheckRetries > 10 then
|
||||
posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: waypoints locked, too many tries, unclogging cavebot and proceeding")
|
||||
return false
|
||||
elseif (tilePos.z == player:getPosition().z) and (getDistanceBetween(player:getPosition(), tilePos) <= tonumber(data[2])) then
|
||||
posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: position reached, proceeding")
|
||||
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 "last" .. "," .. "10" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Location Check",
|
||||
description="label name, accepted dist from coordinates, x, y, z",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
@ -0,0 +1,69 @@
|
||||
-- auto recording for cavebot
|
||||
CaveBot.Recorder = {}
|
||||
|
||||
local isEnabled = nil
|
||||
local lastPos = nil
|
||||
|
||||
local function setup()
|
||||
local function addPosition(pos)
|
||||
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
lastPos = pos
|
||||
end
|
||||
local function addStairs(pos)
|
||||
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z .. ",0", true)
|
||||
lastPos = pos
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not lastPos then
|
||||
-- first step
|
||||
addPosition(oldPos)
|
||||
elseif newPos.z ~= oldPos.z or math.abs(oldPos.x - newPos.x) > 1 or math.abs(oldPos.y - newPos.y) > 1 then
|
||||
-- stairs/teleport
|
||||
addStairs(oldPos)
|
||||
elseif math.max(math.abs(lastPos.x - newPos.x), math.abs(lastPos.y - newPos.y)) > 5 then
|
||||
-- 5 steps from last pos
|
||||
addPosition(newPos)
|
||||
end
|
||||
end)
|
||||
|
||||
onUse(function(pos, itemId, stackPos, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if pos.x ~= 0xFFFF then
|
||||
lastPos = pos
|
||||
CaveBot.addAction("use", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
end
|
||||
end)
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not target:isItem() then return end
|
||||
local targetPos = target:getPosition()
|
||||
if targetPos.x == 0xFFFF then return end
|
||||
lastPos = pos
|
||||
CaveBot.addAction("usewith", itemId .. "," .. targetPos.x .. "," .. targetPos.y .. "," .. targetPos.z, true)
|
||||
end)
|
||||
end
|
||||
|
||||
CaveBot.Recorder.isOn = function()
|
||||
return isEnabled
|
||||
end
|
||||
|
||||
CaveBot.Recorder.enable = function()
|
||||
CaveBot.setOff()
|
||||
if isEnabled == nil then
|
||||
setup()
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(true)
|
||||
isEnabled = true
|
||||
lastPos = nil
|
||||
end
|
||||
|
||||
CaveBot.Recorder.disable = function()
|
||||
if isEnabled == true then
|
||||
isEnabled = false
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(false)
|
||||
CaveBot.save()
|
||||
end
|
@ -0,0 +1,76 @@
|
||||
CaveBot.Extensions.SellAll = {}
|
||||
|
||||
local sellAllCap = 0
|
||||
CaveBot.Extensions.SellAll.setup = function()
|
||||
CaveBot.registerAction("SellAll", "#C300FF", function(value, retries)
|
||||
local val = string.split(value, ",")
|
||||
local wait
|
||||
|
||||
-- table formatting
|
||||
for i, v in ipairs(val) do
|
||||
v = v:trim()
|
||||
v = tonumber(v) or v
|
||||
val[i] = v
|
||||
end
|
||||
|
||||
if table.find(val, "yes", true) then
|
||||
wait = true
|
||||
end
|
||||
|
||||
local npcName = val[1]
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[SellAll]: NPC not found! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if retries > 10 then
|
||||
print("CaveBot[SellAll]: can't sell, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if freecap() == sellAllCap then
|
||||
sellAllCap = 0
|
||||
print("CaveBot[SellAll]: Sold everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
CaveBot.OpenNpcTrade()
|
||||
delay(storage.extras.talkDelay*2)
|
||||
return "retry"
|
||||
else
|
||||
sellAllCap = freecap()
|
||||
end
|
||||
|
||||
storage.cavebotSell = storage.cavebotSell or {}
|
||||
for i, item in ipairs(storage.cavebotSell) do
|
||||
local data = type(item) == 'number' and item or item.id
|
||||
if not table.find(val, data) then
|
||||
table.insert(val, data)
|
||||
end
|
||||
end
|
||||
|
||||
table.dump(val)
|
||||
|
||||
modules.game_npctrade.sellAll(wait, val)
|
||||
if wait then
|
||||
print("CaveBot[SellAll]: Sold All with delay")
|
||||
else
|
||||
print("CaveBot[SellAll]: Sold All without delay")
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("sellall", "sell all", {
|
||||
value="NPC",
|
||||
title="Sell All",
|
||||
description="NPC Name, 'yes' if sell with delay, exceptions: id separated by comma",
|
||||
})
|
||||
end
|
186
modules/game_bot/default_configs/vBot_4.8/cavebot/stand_lure.lua
Normal file
@ -0,0 +1,186 @@
|
||||
CaveBot.Extensions.StandLure = {}
|
||||
local enable = nil
|
||||
|
||||
local function modPos(dir)
|
||||
local y = 0
|
||||
local x = 0
|
||||
|
||||
if dir == 0 then
|
||||
y = -1
|
||||
elseif dir == 1 then
|
||||
x = 1
|
||||
elseif dir == 2 then
|
||||
y = 1
|
||||
elseif dir == 3 then
|
||||
x = -1
|
||||
elseif dir == 4 then
|
||||
y = -1
|
||||
x = 1
|
||||
elseif dir == 5 then
|
||||
y = 1
|
||||
x = 1
|
||||
elseif dir == 6 then
|
||||
y = 1
|
||||
x = -1
|
||||
elseif dir == 7 then
|
||||
y = -1
|
||||
x = -1
|
||||
end
|
||||
|
||||
return {x, y}
|
||||
end
|
||||
local function reset(delay)
|
||||
if type(Supplies.hasEnough()) == 'table' then
|
||||
return
|
||||
end
|
||||
delay = delay or 0
|
||||
CaveBot.delay(delay)
|
||||
if delay == nil then
|
||||
enable = nil
|
||||
end
|
||||
end
|
||||
|
||||
local resetRetries = false
|
||||
CaveBot.Extensions.StandLure.setup = function()
|
||||
CaveBot.registerAction(
|
||||
"rushlure",
|
||||
"#FF0090",
|
||||
function(value, retries)
|
||||
local nextPos = nil
|
||||
local data = string.split(value, ",")
|
||||
if not data[1] then
|
||||
warn("Invalid cavebot lure action value. It should be position (x,y,z), delay(ms) is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if type(Supplies.hasEnough()) == 'table' then -- do not execute if no supplies
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = {x = tonumber(data[1]), y = tonumber(data[2]), z = tonumber(data[3])}
|
||||
|
||||
local delayTime = data[4] and tonumber(data[4]) or 1000
|
||||
if not data[5] then
|
||||
enable = nil
|
||||
elseif data[5] == "yes" then
|
||||
enable = true
|
||||
else
|
||||
enable = false
|
||||
end
|
||||
|
||||
delay(100)
|
||||
|
||||
if retries > 50 and not resetRetries then
|
||||
reset()
|
||||
warn("[Rush Lure] Too many tries, can't reach position")
|
||||
return false -- can't stand on tile
|
||||
end
|
||||
|
||||
if resetRetries then
|
||||
resetRetries = false
|
||||
end
|
||||
|
||||
if distanceFromPlayer(pos) > 30 then
|
||||
reset()
|
||||
return false -- not reachable
|
||||
end
|
||||
|
||||
local playerPos = player:getPosition()
|
||||
local pathWithoutMonsters = findPath(playerPos, pos, 30, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = true, precision = 0})
|
||||
local pathWithMonsters = findPath(playerPos, pos, maxDist, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = false, precision = 0 })
|
||||
|
||||
if not pathWithoutMonsters then
|
||||
reset()
|
||||
warn("[Rush Lure] No possible path to reach position, skipping.")
|
||||
return false -- spot is unreachable
|
||||
elseif pathWithoutMonsters and not pathWithMonsters then
|
||||
local foundMonster = false
|
||||
for i, dir in ipairs(pathWithoutMonsters) do
|
||||
local dirs = modPos(dir)
|
||||
nextPos = nextPos or playerPos
|
||||
nextPos.x = nextPos.x + dirs[1]
|
||||
nextPos.y = nextPos.y + dirs[2]
|
||||
|
||||
|
||||
local tile = g_map.getTile(nextPos)
|
||||
if tile then
|
||||
if tile:hasCreature() then
|
||||
local creature = tile:getCreatures()[1]
|
||||
local hppc = creature:getHealthPercent()
|
||||
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
|
||||
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
|
||||
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
|
||||
if path then
|
||||
creature:setMarked('#00FF00')
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
attack(creature)
|
||||
end
|
||||
g_game.setChaseMode(1)
|
||||
resetRetries = true -- reset retries, we are trying to unclog the cavebot
|
||||
delay(100)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not g_game.getAttackingCreature() then
|
||||
reset()
|
||||
warn("[Rush Lure] No path, no blocking monster, skipping.")
|
||||
return false -- no other way
|
||||
end
|
||||
end
|
||||
|
||||
-- reaching position, delay targetbot in process
|
||||
if not CaveBot.MatchPosition(pos, 0) then
|
||||
TargetBot.delay(300)
|
||||
CaveBot.walkTo(pos, 30, { ignoreCreatures = false, ignoreFields = true, ignoreNonPathable = true, precision = 0})
|
||||
delay(100)
|
||||
resetRetries = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
TargetBot.setOn()
|
||||
reset(delayTime)
|
||||
return true
|
||||
end
|
||||
)
|
||||
|
||||
CaveBot.Editor.registerAction(
|
||||
"rushlure",
|
||||
"rush lure",
|
||||
{
|
||||
value = function()
|
||||
return posx() .. "," .. posy() .. "," .. posz() .. ",1000"
|
||||
end,
|
||||
title = "Stand Lure",
|
||||
description = "Run to position(x,y,z), delay(ms), targetbot on/off (yes/no)",
|
||||
multiline = false,
|
||||
validation = [[\d{1,5},\d{1,5},\d{1,2},\d{1,5}(?:,(yes|no)$|$)]]
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local next = false
|
||||
schedule(5, function() -- delay because cavebot.lua is loaded after this file
|
||||
modules.game_bot.connect(CaveBotList(), {
|
||||
onChildFocusChange = function(widget, newChild, oldChild)
|
||||
|
||||
if oldChild and oldChild.action == "rushlure" then
|
||||
next = true
|
||||
return
|
||||
end
|
||||
|
||||
if next then
|
||||
if enable then
|
||||
TargetBot.setOn()
|
||||
elseif enable == false then
|
||||
TargetBot.setOff()
|
||||
end
|
||||
|
||||
enable = nil -- reset
|
||||
next = false
|
||||
end
|
||||
end})
|
||||
end)
|
@ -0,0 +1,137 @@
|
||||
CaveBot.Extensions.SupplyCheck = {}
|
||||
|
||||
local supplyRetries = 0
|
||||
local missedChecks = 0
|
||||
local rawRound = 0
|
||||
local time = now
|
||||
vBot.CaveBotData =
|
||||
vBot.CaveBotData or
|
||||
{
|
||||
refills = 0,
|
||||
rounds = 0,
|
||||
time = {},
|
||||
lastRefill = os.time(),
|
||||
refillTime = {}
|
||||
}
|
||||
|
||||
local function setCaveBotData(hunting)
|
||||
if hunting then
|
||||
supplyRetries = supplyRetries + 1
|
||||
else
|
||||
supplyRetries = 0
|
||||
table.insert(vBot.CaveBotData.refillTime, os.difftime(os.time() - vBot.CaveBotData.lastRefill))
|
||||
vBot.CaveBotData.lastRefill = os.time()
|
||||
vBot.CaveBotData.refills = vBot.CaveBotData.refills + 1
|
||||
end
|
||||
|
||||
table.insert(vBot.CaveBotData.time, rawRound)
|
||||
vBot.CaveBotData.rounds = vBot.CaveBotData.rounds + 1
|
||||
missedChecks = 0
|
||||
end
|
||||
|
||||
CaveBot.Extensions.SupplyCheck.setup = function()
|
||||
CaveBot.registerAction(
|
||||
"supplyCheck",
|
||||
"#db5a5a",
|
||||
function(value)
|
||||
local data = string.split(value, ",")
|
||||
local round = 0
|
||||
rawRound = 0
|
||||
local label = data[1]:trim()
|
||||
local pos = nil
|
||||
if #data == 4 then
|
||||
pos = {x = tonumber(data[2]), y = tonumber(data[3]), z = tonumber(data[4])}
|
||||
end
|
||||
|
||||
if pos then
|
||||
if missedChecks >= 4 then
|
||||
missedChecks = 0
|
||||
supplyRetries = 0
|
||||
print("CaveBot[SupplyCheck]: Missed 5 supply checks, proceeding with waypoints")
|
||||
return true
|
||||
end
|
||||
if getDistanceBetween(player:getPosition(), pos) > 10 then
|
||||
missedChecks = missedChecks + 1
|
||||
print("CaveBot[SupplyCheck]: Missed supply check! " .. 5 - missedChecks .. " tries left before skipping.")
|
||||
return CaveBot.gotoLabel(label)
|
||||
end
|
||||
end
|
||||
|
||||
if time then
|
||||
rawRound = math.ceil((now - time) / 1000)
|
||||
round = rawRound .. "s"
|
||||
else
|
||||
round = ""
|
||||
end
|
||||
time = now
|
||||
|
||||
local softCount = itemAmount(6529) + itemAmount(3549)
|
||||
local supplyData = Supplies.hasEnough()
|
||||
local supplyInfo = Supplies.getAdditionalData()
|
||||
|
||||
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)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.imbues.enabled and player:getSkillLevel(11) == 0) then
|
||||
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.stamina.enabled and stamina() < tonumber(supplyInfo.stamina.value)) then
|
||||
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.softBoots.enabled and softCount < 1) then
|
||||
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif type(supplyData) == "table" then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. supplyData.id .. "(only " .. supplyData.amount .. " left). Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.capacity.enabled and freecap() < tonumber(supplyInfo.capacity.value)) then
|
||||
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
else
|
||||
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. supplyRetries .. "/" .. (storage.extras.huntRoutes or 50) .. "). Last round took: " .. round)
|
||||
setCaveBotData(true)
|
||||
return CaveBot.gotoLabel(label)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
CaveBot.Editor.registerAction(
|
||||
"supplycheck",
|
||||
"supply check",
|
||||
{
|
||||
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
|
178
modules/game_bot/default_configs/vBot_4.8/cavebot/tasker.lua
Normal file
@ -0,0 +1,178 @@
|
||||
CaveBot.Extensions.Tasker = {}
|
||||
|
||||
local dataValidationFailed = function()
|
||||
print("CaveBot[Tasker]: data validation failed! incorrect data, check cavebot/tasker for more info")
|
||||
return false
|
||||
end
|
||||
|
||||
-- miniconfig
|
||||
local talkDelay = storage.extras.talkDelay
|
||||
if not storage.caveBotTasker then
|
||||
storage.caveBotTasker = {
|
||||
inProgress = false,
|
||||
monster = "",
|
||||
taskName = "",
|
||||
count = 0,
|
||||
max = 0
|
||||
}
|
||||
end
|
||||
|
||||
local resetTaskData = function()
|
||||
storage.caveBotTasker.inProgress = false
|
||||
storage.caveBotTasker.monster = ""
|
||||
storage.caveBotTasker.monster2 = ""
|
||||
storage.caveBotTasker.taskName = ""
|
||||
storage.caveBotTasker.count = 0
|
||||
storage.caveBotTasker.max = 0
|
||||
end
|
||||
|
||||
CaveBot.Extensions.Tasker.setup = function()
|
||||
CaveBot.registerAction("Tasker", "#FF0090", function(value, retries)
|
||||
local taskName = ""
|
||||
local monster = ""
|
||||
local monster2 = ""
|
||||
local count = 0
|
||||
local label1 = ""
|
||||
local label2 = ""
|
||||
local task
|
||||
|
||||
local data = string.split(value, ",")
|
||||
if not data or #data < 1 then
|
||||
dataValidationFailed()
|
||||
end
|
||||
local marker = tonumber(data[1])
|
||||
|
||||
if not marker then
|
||||
dataValidationFailed()
|
||||
resetTaskData()
|
||||
elseif marker == 1 then
|
||||
if getNpcs(3) == 0 then
|
||||
print("CaveBot[Tasker]: no NPC found in range! skipping")
|
||||
return false
|
||||
end
|
||||
if #data ~= 4 and #data ~= 5 then
|
||||
dataValidationFailed()
|
||||
resetTaskData()
|
||||
else
|
||||
taskName = data[2]:lower():trim()
|
||||
count = tonumber(data[3]:trim())
|
||||
monster = data[4]:lower():trim()
|
||||
if #data == 5 then
|
||||
monster2 = data[5]:lower():trim()
|
||||
end
|
||||
end
|
||||
elseif marker == 2 then
|
||||
if #data ~= 3 then
|
||||
dataValidationFailed()
|
||||
else
|
||||
label1 = data[2]:lower():trim()
|
||||
label2 = data[3]:lower():trim()
|
||||
end
|
||||
elseif marker == 3 then
|
||||
if getNpcs(3) == 0 then
|
||||
print("CaveBot[Tasker]: no NPC found in range! skipping")
|
||||
return false
|
||||
end
|
||||
if #data ~= 1 then
|
||||
dataValidationFailed()
|
||||
end
|
||||
end
|
||||
|
||||
-- let's cover markers now
|
||||
if marker == 1 then -- starting task
|
||||
CaveBot.Conversation("hi", "task", taskName, "yes")
|
||||
delay(talkDelay*4)
|
||||
|
||||
storage.caveBotTasker.monster = monster
|
||||
if monster2 then storage.caveBotTasker.monster2 = monster2 end
|
||||
storage.caveBotTasker.taskName = taskName
|
||||
storage.caveBotTasker.inProgress = true
|
||||
storage.caveBotTasker.max = count
|
||||
storage.caveBotTasker.count = 0
|
||||
|
||||
print("CaveBot[Tasker]: taken task for: " .. monster .. " x" .. count)
|
||||
return true
|
||||
elseif marker == 2 then -- only checking
|
||||
if not storage.caveBotTasker.inProgress then
|
||||
CaveBot.gotoLabel(label2)
|
||||
print("CaveBot[Tasker]: there is no task in progress so going to take one.")
|
||||
return true
|
||||
end
|
||||
|
||||
local max = storage.caveBotTasker.max
|
||||
local count = storage.caveBotTasker.count
|
||||
|
||||
if count >= max then
|
||||
CaveBot.gotoLabel(label2)
|
||||
print("CaveBot[Tasker]: task completed: " .. storage.caveBotTasker.taskName)
|
||||
return true
|
||||
else
|
||||
CaveBot.gotoLabel(label1)
|
||||
print("CaveBot[Tasker]: task in progress, left: " .. max - count .. " " .. storage.caveBotTasker.taskName)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
elseif marker == 3 then -- reporting task
|
||||
CaveBot.Conversation("hi", "report", "task")
|
||||
delay(talkDelay*3)
|
||||
|
||||
resetTaskData()
|
||||
print("CaveBot[Tasker]: task reported, done")
|
||||
return true
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("tasker", "tasker", {
|
||||
value=[[ There is 3 scenarios for this extension, as example we will use medusa:
|
||||
|
||||
1. start task,
|
||||
parameters:
|
||||
- scenario for extension: 1
|
||||
- task name in gryzzly adams: medusae
|
||||
- monster count: 500
|
||||
- monster name to track: medusa
|
||||
- optional, monster name 2:
|
||||
2. check status,
|
||||
to be used on refill to decide whether to go back or spawn or go give task back
|
||||
parameters:
|
||||
- scenario for extension: 2
|
||||
- label if task in progress: skipTask
|
||||
- label if task done: taskDone
|
||||
3. report task,
|
||||
parameters:
|
||||
- scenario for extension: 3
|
||||
|
||||
Strong suggestion, almost mandatory - USE POS CHECK to verify position! this module will only check if there is ANY npc in range!
|
||||
|
||||
when begin remove all the text and leave just a single string of parameters
|
||||
some examples:
|
||||
|
||||
2, skipReport, goReport
|
||||
3
|
||||
1, drakens, 500, draken warmaster, draken spellweaver
|
||||
1, medusae, 500, medusa]],
|
||||
title="Tasker",
|
||||
multiline = true
|
||||
})
|
||||
end
|
||||
|
||||
local regex = "Loot of ([a-z])* ([a-z A-Z]*):"
|
||||
local regex2 = "Loot of ([a-z A-Z]*):"
|
||||
onTextMessage(function(mode, text)
|
||||
-- if CaveBot.isOff() then return end
|
||||
if not text:lower():find("loot of") then return end
|
||||
if #regexMatch(text, regex) == 1 and #regexMatch(text, regex)[1] == 3 then
|
||||
monster = regexMatch(text, regex)[1][3]
|
||||
elseif #regexMatch(text, regex2) == 1 and #regexMatch(text, regex2)[1] == 2 then
|
||||
monster = regexMatch(text, regex2)[1][2]
|
||||
end
|
||||
|
||||
local m1 = storage.caveBotTasker.monster
|
||||
local m2 = storage.caveBotTasker.monster2
|
||||
|
||||
if monster == m1 or monster == m2 and storage.caveBotTasker.count then
|
||||
storage.caveBotTasker.count = storage.caveBotTasker.count + 1
|
||||
end
|
||||
end)
|
40
modules/game_bot/default_configs/vBot_4.8/cavebot/travel.lua
Normal file
@ -0,0 +1,40 @@
|
||||
CaveBot.Extensions.Travel = {}
|
||||
|
||||
CaveBot.Extensions.Travel.setup = function()
|
||||
CaveBot.registerAction("Travel", "#db5a5a", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
if #data < 2 then
|
||||
warn("CaveBot[Travel]: incorrect travel value!")
|
||||
return false
|
||||
end
|
||||
|
||||
local npcName = data[1]:trim()
|
||||
local dest = data[2]:trim()
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Travel]: too many tries, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[Travel]: NPC not found, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
CaveBot.Travel(dest)
|
||||
delay(storage.extras.talkDelay*3)
|
||||
print("CaveBot[Travel]: travel action finished")
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("travel", "travel", {
|
||||
value="NPC name, city",
|
||||
title="Travel",
|
||||
description="NPC name, City name, delay in ms(default is 200ms)",
|
||||
})
|
||||
end
|
@ -0,0 +1,93 @@
|
||||
-- walking
|
||||
local expectedDirs = {}
|
||||
local isWalking = {}
|
||||
local walkPath = {}
|
||||
local walkPathIter = 0
|
||||
|
||||
CaveBot.resetWalking = function()
|
||||
expectedDirs = {}
|
||||
walkPath = {}
|
||||
isWalking = false
|
||||
end
|
||||
|
||||
CaveBot.doWalking = function()
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs == 0 then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs >= 3 then
|
||||
CaveBot.resetWalking()
|
||||
end
|
||||
local dir = walkPath[walkPathIter]
|
||||
if dir then
|
||||
g_game.walk(dir, false)
|
||||
table.insert(expectedDirs, dir)
|
||||
walkPathIter = walkPathIter + 1
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- called when player position has been changed (step has been confirmed by server)
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if not oldPos or not newPos then return end
|
||||
|
||||
local dirs = {{NorthWest, North, NorthEast}, {West, 8, East}, {SouthWest, South, SouthEast}}
|
||||
local dir = dirs[newPos.y - oldPos.y + 2]
|
||||
if dir then
|
||||
dir = dir[newPos.x - oldPos.x + 2]
|
||||
end
|
||||
if not dir then
|
||||
dir = 8 -- 8 is invalid dir, it's fine
|
||||
end
|
||||
|
||||
if not isWalking or not expectedDirs[1] then
|
||||
-- some other walk action is taking place (for example use on ladder), wait
|
||||
walkPath = {}
|
||||
CaveBot.delay(CaveBot.Config.get("ping") + player:getStepDuration(false, dir) + 150)
|
||||
return
|
||||
end
|
||||
|
||||
if expectedDirs[1] ~= dir then
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
else
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
table.remove(expectedDirs, 1)
|
||||
if CaveBot.Config.get("mapClick") and #expectedDirs > 0 then
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.walkTo = function(dest, maxDist, params)
|
||||
local path = getPath(player:getPosition(), dest, maxDist, params)
|
||||
if not path or not path[1] then
|
||||
return false
|
||||
end
|
||||
local dir = path[1]
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
local ret = autoWalk(path)
|
||||
if ret then
|
||||
isWalking = true
|
||||
expectedDirs = path
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + math.max(CaveBot.Config.get("ping") + player:getStepDuration(false, dir), player:getStepDuration(false, dir) * 2))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
g_game.walk(dir, false)
|
||||
isWalking = true
|
||||
walkPath = path
|
||||
walkPathIter = 2
|
||||
expectedDirs = { dir }
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
@ -0,0 +1,56 @@
|
||||
CaveBot.Extensions.Withdraw = {}
|
||||
|
||||
CaveBot.Extensions.Withdraw.setup = function()
|
||||
CaveBot.registerAction("withdraw", "#002FFF", function(value, retries)
|
||||
-- validation
|
||||
local data = string.split(value, ",")
|
||||
if #data ~= 3 then
|
||||
print("CaveBot[Withdraw]: incorrect data! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
-- variables declaration
|
||||
local source = tonumber(data[1])
|
||||
local id = tonumber(data[2])
|
||||
local amount = tonumber(data[3])
|
||||
|
||||
-- validation for correct values
|
||||
if not id or not amount then
|
||||
print("CaveBot[Withdraw]: incorrect id or amount! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
-- check for retries
|
||||
if retries > 100 then
|
||||
print("CaveBot[Withdraw]: actions limit reached, proceeding")
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- check for items
|
||||
if itemAmount(id) >= amount then
|
||||
print("CaveBot[Withdraw]: enough items, proceeding")
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
statusMessage("[Withdraw] withdrawing item: " ..id.. " x"..amount)
|
||||
CaveBot.WithdrawItem(id, amount, source)
|
||||
CaveBot.PingDelay()
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("withdraw", "withdraw", {
|
||||
value="source,id,amount",
|
||||
title="Withdraw Items",
|
||||
description="index/inbox, item id and amount",
|
||||
})
|
||||
end
|
@ -0,0 +1,99 @@
|
||||
|
||||
TargetBot.Creature = {}
|
||||
TargetBot.Creature.configsCache = {}
|
||||
TargetBot.Creature.cached = 0
|
||||
|
||||
TargetBot.Creature.resetConfigs = function()
|
||||
TargetBot.targetList:destroyChildren()
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
end
|
||||
|
||||
TargetBot.Creature.resetConfigsCache = function()
|
||||
TargetBot.Creature.configsCache = {}
|
||||
TargetBot.Creature.cached = 0
|
||||
end
|
||||
|
||||
TargetBot.Creature.addConfig = function(config, focus)
|
||||
if type(config) ~= 'table' or type(config.name) ~= 'string' then
|
||||
return error("Invalid targetbot creature config (missing name)")
|
||||
end
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
|
||||
if not config.regex then
|
||||
config.regex = ""
|
||||
for part in string.gmatch(config.name, "[^,]+") do
|
||||
if config.regex:len() > 0 then
|
||||
config.regex = config.regex .. "|"
|
||||
end
|
||||
config.regex = config.regex .. "^" .. part:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
end
|
||||
end
|
||||
|
||||
local widget = UI.createWidget("TargetBotEntry", TargetBot.targetList)
|
||||
widget:setText(config.name)
|
||||
widget.value = config
|
||||
|
||||
widget.onDoubleClick = function(entry) -- edit on double click
|
||||
schedule(20, function() -- schedule to have correct focus
|
||||
TargetBot.Creature.edit(entry.value, function(newConfig)
|
||||
entry:setText(newConfig.name)
|
||||
entry.value = newConfig
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
if focus then
|
||||
widget:focus()
|
||||
TargetBot.targetList:ensureChildVisible(widget)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
TargetBot.Creature.getConfigs = function(creature)
|
||||
if not creature then return {} end
|
||||
local name = creature:getName():trim():lower()
|
||||
-- this function may be slow, so it will be using cache
|
||||
if TargetBot.Creature.configsCache[name] then
|
||||
return TargetBot.Creature.configsCache[name]
|
||||
end
|
||||
local configs = {}
|
||||
for _, config in ipairs(TargetBot.targetList:getChildren()) do
|
||||
if regexMatch(name, config.value.regex)[1] then
|
||||
table.insert(configs, config.value)
|
||||
end
|
||||
end
|
||||
if TargetBot.Creature.cached > 1000 then
|
||||
TargetBot.Creature.resetConfigsCache() -- too big cache size, reset
|
||||
end
|
||||
TargetBot.Creature.configsCache[name] = configs -- add to cache
|
||||
TargetBot.Creature.cached = TargetBot.Creature.cached + 1
|
||||
return configs
|
||||
end
|
||||
|
||||
TargetBot.Creature.calculateParams = function(creature, path)
|
||||
local configs = TargetBot.Creature.getConfigs(creature)
|
||||
local priority = 0
|
||||
local danger = 0
|
||||
local selectedConfig = nil
|
||||
for _, config in ipairs(configs) do
|
||||
local config_priority = TargetBot.Creature.calculatePriority(creature, config, path)
|
||||
if config_priority > priority then
|
||||
priority = config_priority
|
||||
danger = TargetBot.Creature.calculateDanger(creature, config, path)
|
||||
selectedConfig = config
|
||||
end
|
||||
end
|
||||
return {
|
||||
config = selectedConfig,
|
||||
creature = creature,
|
||||
danger = danger,
|
||||
priority = priority
|
||||
}
|
||||
end
|
||||
|
||||
TargetBot.Creature.calculateDanger = function(creature, config, path)
|
||||
-- config is based on creature_editor
|
||||
return config.danger
|
||||
end
|
@ -0,0 +1,245 @@
|
||||
local targetBotLure = false
|
||||
local targetCount = 0
|
||||
local delayValue = 0
|
||||
local lureMax = 0
|
||||
local anchorPosition = nil
|
||||
local lastCall = now
|
||||
local delayFrom = nil
|
||||
local dynamicLureDelay = false
|
||||
|
||||
function getWalkableTilesCount(position)
|
||||
local count = 0
|
||||
|
||||
for i, tile in pairs(getNearTiles(position)) do
|
||||
if tile:isWalkable() or tile:hasCreature() then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function rePosition(minTiles)
|
||||
minTiles = minTiles or 8
|
||||
if now - lastCall < 500 then return end
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(pPos)
|
||||
local playerTilesCount = getWalkableTilesCount(pPos)
|
||||
local tilesTable = {}
|
||||
|
||||
if playerTilesCount > minTiles then return end
|
||||
for i, tile in ipairs(tiles) do
|
||||
tilesTable[tile] = not tile:hasCreature() and tile:isWalkable() and getWalkableTilesCount(tile:getPosition()) or nil
|
||||
end
|
||||
|
||||
local best = 0
|
||||
local target = nil
|
||||
for k,v in pairs(tilesTable) do
|
||||
if v > best and v > playerTilesCount then
|
||||
best = v
|
||||
target = k:getPosition()
|
||||
end
|
||||
end
|
||||
|
||||
if target then
|
||||
lastCall = now
|
||||
return CaveBot.GoTo(target, 0)
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority}
|
||||
if player:isWalking() then
|
||||
lastWalk = now
|
||||
end
|
||||
|
||||
local config = params.config
|
||||
local creature = params.creature
|
||||
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
g_game.attack(creature)
|
||||
end
|
||||
|
||||
if not isLooting then -- walk only when not looting
|
||||
TargetBot.Creature.walk(creature, config, targets)
|
||||
end
|
||||
|
||||
-- attacks
|
||||
local mana = player:getMana()
|
||||
if config.useGroupAttack and config.groupAttackSpell:len() > 1 and mana > config.minManaGroup then
|
||||
local creatures = g_map.getSpectatorsInRange(player:getPosition(), false, config.groupAttackRadius, config.groupAttackRadius)
|
||||
local playersAround = false
|
||||
local monsters = 0
|
||||
for _, creature in ipairs(creatures) do
|
||||
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
|
||||
playersAround = true
|
||||
elseif creature:isMonster() then
|
||||
monsters = monsters + 1
|
||||
end
|
||||
end
|
||||
if monsters >= config.groupAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
|
||||
if TargetBot.sayAttackSpell(config.groupAttackSpell, config.groupAttackDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.useGroupAttackRune and config.groupAttackRune > 100 then
|
||||
local creatures = g_map.getSpectatorsInRange(creature:getPosition(), false, config.groupRuneAttackRadius, config.groupRuneAttackRadius)
|
||||
local playersAround = false
|
||||
local monsters = 0
|
||||
for _, creature in ipairs(creatures) do
|
||||
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
|
||||
playersAround = true
|
||||
elseif creature:isMonster() then
|
||||
monsters = monsters + 1
|
||||
end
|
||||
end
|
||||
if monsters >= config.groupRuneAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
|
||||
if TargetBot.useAttackItem(config.groupAttackRune, 0, creature, config.groupRuneAttackDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
if config.useSpellAttack and config.attackSpell:len() > 1 and mana > config.minMana then
|
||||
if TargetBot.sayAttackSpell(config.attackSpell, config.attackSpellDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if config.useRuneAttack and config.attackRune > 100 then
|
||||
if TargetBot.useAttackItem(config.attackRune, 0, creature, config.attackRuneDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Creature.walk = function(creature, config, targets)
|
||||
local cpos = creature:getPosition()
|
||||
local pos = player:getPosition()
|
||||
|
||||
local isTrapped = true
|
||||
local pos = player:getPosition()
|
||||
local dirs = {{-1,1}, {0,1}, {1,1}, {-1, 0}, {1, 0}, {-1, -1}, {0, -1}, {1, -1}}
|
||||
for i=1,#dirs do
|
||||
local tile = g_map.getTile({x=pos.x-dirs[i][1],y=pos.y-dirs[i][2],z=pos.z})
|
||||
if tile and tile:isWalkable(false) then
|
||||
isTrapped = false
|
||||
end
|
||||
end
|
||||
|
||||
-- data for external dynamic lure
|
||||
if config.lureMin and config.lureMax and config.dynamicLure then
|
||||
if config.lureMin >= targets then
|
||||
targetBotLure = true
|
||||
elseif targets >= config.lureMax then
|
||||
targetBotLure = false
|
||||
end
|
||||
end
|
||||
targetCount = targets
|
||||
delayValue = config.lureDelay
|
||||
|
||||
if config.lureMax then
|
||||
lureMax = config.lureMax
|
||||
end
|
||||
|
||||
dynamicLureDelay = config.dynamicLureDelay
|
||||
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
|
||||
if targetBotLure then
|
||||
anchorPosition = nil
|
||||
return TargetBot.allowCaveBot(150)
|
||||
else
|
||||
if targets < config.lureCount then
|
||||
if config.lureCavebot then
|
||||
anchorPosition = nil
|
||||
return TargetBot.allowCaveBot(150)
|
||||
else
|
||||
local path = findPath(pos, cpos, 5, {ignoreNonPathable=true, precision=2})
|
||||
if path then
|
||||
return TargetBot.walkTo(cpos, 10, {marginMin=5, marginMax=6, ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
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})
|
||||
end
|
||||
elseif config.keepDistance then
|
||||
if not anchorPosition or distanceFromPlayer(anchorPosition) > config.anchorRange then
|
||||
anchorPosition = pos
|
||||
end
|
||||
if #currentDistance ~= config.keepDistanceRange and #currentDistance ~= config.keepDistanceRange + 1 then
|
||||
if config.anchor and anchorPosition and getDistanceBetween(pos, anchorPosition) <= config.anchorRange*2 then
|
||||
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1, maxDistanceFrom={anchorPosition, config.anchorRange}})
|
||||
else
|
||||
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--target only movement
|
||||
if config.avoidAttacks then
|
||||
local diffx = cpos.x - pos.x
|
||||
local diffy = cpos.y - pos.y
|
||||
local candidates = {}
|
||||
if math.abs(diffx) == 1 and diffy == 0 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x, y=pos.y+1, z=pos.z}}
|
||||
elseif diffx == 0 and math.abs(diffy) == 1 then
|
||||
candidates = {{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z}}
|
||||
end
|
||||
for _, candidate in ipairs(candidates) do
|
||||
local tile = g_map.getTile(candidate)
|
||||
if tile and tile:isWalkable() then
|
||||
return TargetBot.walkTo(candidate, 2, {ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
elseif config.faceMonster then
|
||||
local diffx = cpos.x - pos.x
|
||||
local diffy = cpos.y - pos.y
|
||||
local candidates = {}
|
||||
if diffx == 1 and diffy == 1 then
|
||||
candidates = {{x=pos.x+1, y=pos.y, z=pos.z}, {x=pos.x, y=pos.y-1, z=pos.z}}
|
||||
elseif diffx == -1 and diffy == 1 then
|
||||
candidates = {{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x, y=pos.y-1, z=pos.z}}
|
||||
elseif diffx == -1 and diffy == -1 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x-1, y=pos.y, z=pos.z}}
|
||||
elseif diffx == 1 and diffy == -1 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z}}
|
||||
else
|
||||
local dir = player:getDirection()
|
||||
if diffx == 1 and dir ~= 1 then turn(1)
|
||||
elseif diffx == -1 and dir ~= 3 then turn(3)
|
||||
elseif diffy == 1 and dir ~= 2 then turn(2)
|
||||
elseif diffy == -1 and dir ~= 0 then turn(0)
|
||||
end
|
||||
end
|
||||
for _, candidate in ipairs(candidates) do
|
||||
local tile = g_map.getTile(candidate)
|
||||
if tile and tile:isWalkable() then
|
||||
return TargetBot.walkTo(candidate, 2, {ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOff() then return end
|
||||
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 targetCount < (delayFrom or lureMax/2) or not target() then return end
|
||||
CaveBot.delay(delayValue or 0)
|
||||
end)
|
@ -0,0 +1,106 @@
|
||||
TargetBot.Creature.edit = function(config, callback) -- callback = function(newConfig)
|
||||
config = config or {}
|
||||
|
||||
local editor = UI.createWindow('TargetBotCreatureEditorWindow')
|
||||
local values = {} -- (key, function returning value of key)
|
||||
|
||||
editor.name:setText(config.name or "")
|
||||
table.insert(values, {"name", function() return editor.name:getText() end})
|
||||
|
||||
local addScrollBar = function(id, title, min, max, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorScrollBar', editor.content.left)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
widget.text:setText(title .. ": " .. value)
|
||||
end
|
||||
widget.scroll:setRange(min, max)
|
||||
if max-min > 1000 then
|
||||
widget.scroll:setStep(100)
|
||||
elseif max-min > 100 then
|
||||
widget.scroll:setStep(10)
|
||||
end
|
||||
widget.scroll:setValue(config[id] or defaultValue)
|
||||
widget.scroll.onValueChange(widget.scroll, widget.scroll:getValue())
|
||||
table.insert(values, {id, function() return widget.scroll:getValue() end})
|
||||
end
|
||||
|
||||
local addTextEdit = function(id, title, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorTextEdit', editor.content.right)
|
||||
widget.text:setText(title)
|
||||
widget.textEdit:setText(config[id] or defaultValue or "")
|
||||
table.insert(values, {id, function() return widget.textEdit:getText() end})
|
||||
end
|
||||
|
||||
local addCheckBox = function(id, title, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorCheckBox', editor.content.right)
|
||||
widget.onClick = function()
|
||||
widget:setOn(not widget:isOn())
|
||||
end
|
||||
widget:setText(title)
|
||||
if config[id] == nil then
|
||||
widget:setOn(defaultValue)
|
||||
else
|
||||
widget:setOn(config[id])
|
||||
end
|
||||
table.insert(values, {id, function() return widget:isOn() end})
|
||||
end
|
||||
|
||||
local addItem = function(id, title, defaultItem)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorItem', editor.content.right)
|
||||
widget.text:setText(title)
|
||||
widget.item:setItemId(config[id] or defaultItem)
|
||||
table.insert(values, {id, function() return widget.item:getItemId() end})
|
||||
end
|
||||
|
||||
editor.cancel.onClick = function()
|
||||
editor:destroy()
|
||||
end
|
||||
editor.onEscape = editor.cancel.onClick
|
||||
|
||||
editor.ok.onClick = function()
|
||||
local newConfig = {}
|
||||
for _, value in ipairs(values) do
|
||||
newConfig[value[1]] = value[2]()
|
||||
end
|
||||
if newConfig.name:len() < 1 then return end
|
||||
|
||||
newConfig.regex = ""
|
||||
for part in string.gmatch(newConfig.name, "[^,]+") do
|
||||
if newConfig.regex:len() > 0 then
|
||||
newConfig.regex = newConfig.regex .. "|"
|
||||
end
|
||||
newConfig.regex = newConfig.regex .. "^" .. part:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
end
|
||||
|
||||
editor:destroy()
|
||||
callback(newConfig)
|
||||
end
|
||||
|
||||
-- values
|
||||
addScrollBar("priority", "Priority", 0, 10, 1)
|
||||
addScrollBar("danger", "Danger", 0, 10, 1)
|
||||
addScrollBar("maxDistance", "Max distance", 1, 10, 10)
|
||||
addScrollBar("keepDistanceRange", "Keep distance", 1, 5, 1)
|
||||
addScrollBar("anchorRange", "Anchoring Range", 1, 10, 3)
|
||||
addScrollBar("lureCount", "Classic Lure", 0, 5, 1)
|
||||
addScrollBar("lureMin", "Dynamic lure min", 0, 29, 1)
|
||||
addScrollBar("lureMax", "Dynamic lure max", 1, 30, 3)
|
||||
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)
|
||||
addCheckBox("anchor", "Anchoring", false)
|
||||
addCheckBox("dontLoot", "Don't loot", false)
|
||||
addCheckBox("lure", "Lure", false)
|
||||
addCheckBox("lureCavebot", "Lure using cavebot", false)
|
||||
addCheckBox("faceMonster", "Face monsters", false)
|
||||
addCheckBox("avoidAttacks", "Avoid wave attacks", false)
|
||||
addCheckBox("dynamicLure", "Dynamic lure", false)
|
||||
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)
|
||||
addCheckBox("rpSafe", "RP PVP SAFE - (DA)", false)
|
||||
end
|
@ -0,0 +1,164 @@
|
||||
TargetBotCreatureEditorScrollBar < Panel
|
||||
height: 28
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
TargetBotCreatureEditorTextEdit < Panel
|
||||
height: 40
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
TextEdit
|
||||
id: textEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
TargetBotCreatureEditorItem < Panel
|
||||
height: 34
|
||||
margin-top: 7
|
||||
margin-left: 25
|
||||
margin-right: 25
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
TargetBotCreatureEditorCheckBox < BotSwitch
|
||||
height: 20
|
||||
margin-top: 7
|
||||
|
||||
TargetBotCreatureEditorWindow < MainWindow
|
||||
text: TargetBot creature editor
|
||||
width: 500
|
||||
height: 425
|
||||
|
||||
$mobile:
|
||||
height: 300
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
!text: tr('You can use * (any characters) and ? (any character) in target name')
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
text-align: center
|
||||
!text: tr('You can also enter multiple targets, separate them by ,')
|
||||
|
||||
TextEdit
|
||||
id: name
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-left: 90
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: parent.left
|
||||
text: Target name:
|
||||
|
||||
VerticalScrollBar
|
||||
id: contentScroll
|
||||
anchors.top: name.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: help.top
|
||||
step: 28
|
||||
pixels-scroll: true
|
||||
margin-right: -10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
ScrollablePanel
|
||||
id: content
|
||||
anchors.top: name.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: help.top
|
||||
vertical-scrollbar: contentScroll
|
||||
margin-bottom: 10
|
||||
|
||||
Panel
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Button
|
||||
id: help
|
||||
!text: tr('Help & Tutorials')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: 150
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")
|
||||
|
||||
Button
|
||||
id: ok
|
||||
!text: tr('Ok')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: cancel
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
@ -0,0 +1,61 @@
|
||||
TargetBot.Creature.calculatePriority = function(creature, config, path)
|
||||
-- config is based on creature_editor
|
||||
local priority = 0
|
||||
local currentTarget = g_game.getAttackingCreature()
|
||||
|
||||
-- extra priority if it's current target
|
||||
if currentTarget == creature then
|
||||
priority = priority + 1
|
||||
end
|
||||
|
||||
-- check if distance is ok
|
||||
if #path > config.maxDistance then
|
||||
if config.rpSafe then
|
||||
if currentTarget == creature then
|
||||
g_game.cancelAttackAndFollow() -- if not, stop attack (pvp safe)
|
||||
end
|
||||
end
|
||||
return priority
|
||||
end
|
||||
|
||||
-- add config priority
|
||||
priority = priority + config.priority
|
||||
|
||||
-- extra priority for close distance
|
||||
local path_length = #path
|
||||
if path_length == 1 then
|
||||
priority = priority + 10
|
||||
elseif path_length <= 3 then
|
||||
priority = priority + 5
|
||||
end
|
||||
|
||||
-- extra priority for paladin diamond arrows
|
||||
if config.diamondArrows then
|
||||
local mobCount = getCreaturesInArea(creature:getPosition(), diamondArrowArea, 2)
|
||||
priority = priority + (mobCount * 4)
|
||||
|
||||
if config.rpSafe then
|
||||
if getCreaturesInArea(creature:getPosition(), largeRuneArea, 3) > 0 then
|
||||
if currentTarget == creature then
|
||||
g_game.cancelAttackAndFollow()
|
||||
end
|
||||
return 0 -- pvp safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- extra priority for low health
|
||||
if config.chase and creature:getHealthPercent() < 30 then
|
||||
priority = priority + 5
|
||||
elseif creature:getHealthPercent() < 20 then
|
||||
priority = priority + 2.5
|
||||
elseif creature:getHealthPercent() < 40 then
|
||||
priority = priority + 1.5
|
||||
elseif creature:getHealthPercent() < 60 then
|
||||
priority = priority + 0.5
|
||||
elseif creature:getHealthPercent() < 80 then
|
||||
priority = priority + 0.2
|
||||
end
|
||||
|
||||
return priority
|
||||
end
|
324
modules/game_bot/default_configs/vBot_4.8/targetbot/looting.lua
Normal file
@ -0,0 +1,324 @@
|
||||
TargetBot.Looting = {}
|
||||
TargetBot.Looting.list = {} -- list of containers to loot
|
||||
|
||||
local ui
|
||||
local items = {}
|
||||
local containers = {}
|
||||
local itemsById = {}
|
||||
local containersById = {}
|
||||
local dontSave = false
|
||||
|
||||
TargetBot.Looting.setup = function()
|
||||
ui = UI.createWidget("TargetBotLootingPanel")
|
||||
UI.Container(TargetBot.Looting.onItemsUpdate, true, nil, ui.items)
|
||||
UI.Container(TargetBot.Looting.onContainersUpdate, true, nil, ui.containers)
|
||||
ui.everyItem.onClick = function()
|
||||
ui.everyItem:setOn(not ui.everyItem:isOn())
|
||||
TargetBot.save()
|
||||
end
|
||||
ui.maxDangerPanel.value.onTextChange = function()
|
||||
local value = tonumber(ui.maxDangerPanel.value:getText())
|
||||
if not value then
|
||||
ui.maxDangerPanel.value:setText(0)
|
||||
end
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
end
|
||||
ui.minCapacityPanel.value.onTextChange = function()
|
||||
local value = tonumber(ui.minCapacityPanel.value:getText())
|
||||
if not value then
|
||||
ui.minCapacityPanel.value:setText(0)
|
||||
end
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Looting.onItemsUpdate = function()
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
end
|
||||
|
||||
TargetBot.Looting.onContainersUpdate = function()
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
end
|
||||
|
||||
TargetBot.Looting.update = function(data)
|
||||
dontSave = true
|
||||
TargetBot.Looting.list = {}
|
||||
ui.items:setItems(data['items'] or {})
|
||||
ui.containers:setItems(data['containers'] or {})
|
||||
ui.everyItem:setOn(data['everyItem'])
|
||||
ui.maxDangerPanel.value:setText(data['maxDanger'] or 10)
|
||||
ui.minCapacityPanel.value:setText(data['minCapacity'] or 100)
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
dontSave = false
|
||||
--vBot
|
||||
vBot.lootConainers = {}
|
||||
vBot.lootItems = {}
|
||||
for i, item in ipairs(ui.containers:getItems()) do
|
||||
table.insert(vBot.lootConainers, item['id'])
|
||||
end
|
||||
for i, item in ipairs(ui.items:getItems()) do
|
||||
table.insert(vBot.lootItems, item['id'])
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Looting.save = function(data)
|
||||
data['items'] = ui.items:getItems()
|
||||
data['containers'] = ui.containers:getItems()
|
||||
data['maxDanger'] = tonumber(ui.maxDangerPanel.value:getText())
|
||||
data['minCapacity'] = tonumber(ui.minCapacityPanel.value:getText())
|
||||
data['everyItem'] = ui.everyItem:isOn()
|
||||
end
|
||||
|
||||
TargetBot.Looting.updateItemsAndContainers = function()
|
||||
items = ui.items:getItems()
|
||||
containers = ui.containers:getItems()
|
||||
itemsById = {}
|
||||
containersById = {}
|
||||
for i, item in ipairs(items) do
|
||||
itemsById[item.id] = 1
|
||||
end
|
||||
for i, container in ipairs(containers) do
|
||||
containersById[container.id] = 1
|
||||
end
|
||||
end
|
||||
|
||||
local waitTill = 0
|
||||
local waitingForContainer = nil
|
||||
local status = ""
|
||||
local lastFoodConsumption = 0
|
||||
|
||||
TargetBot.Looting.getStatus = function()
|
||||
return status
|
||||
end
|
||||
|
||||
TargetBot.Looting.process = function(targets, dangerLevel)
|
||||
if (not items[1] and not ui.everyItem:isOn()) or not containers[1] then
|
||||
status = ""
|
||||
return false
|
||||
end
|
||||
if dangerLevel > tonumber(ui.maxDangerPanel.value:getText()) then
|
||||
status = "High danger"
|
||||
return false
|
||||
end
|
||||
if player:getFreeCapacity() < tonumber(ui.minCapacityPanel.value:getText()) then
|
||||
status = "No cap"
|
||||
TargetBot.Looting.list = {}
|
||||
return false
|
||||
end
|
||||
local loot = storage.extras.lootLast and TargetBot.Looting.list[#TargetBot.Looting.list] or TargetBot.Looting.list[1]
|
||||
if loot == nil then
|
||||
status = ""
|
||||
return false
|
||||
end
|
||||
|
||||
if waitTill > now then
|
||||
return true
|
||||
end
|
||||
local containers = g_game.getContainers()
|
||||
local lootContainers = TargetBot.Looting.getLootContainers(containers)
|
||||
|
||||
-- check if there's container for loot and has empty space for it
|
||||
if not lootContainers[1] then
|
||||
-- there's no space, don't loot
|
||||
status = "No space"
|
||||
return false
|
||||
end
|
||||
|
||||
status = "Looting"
|
||||
|
||||
for index, container in pairs(containers) do
|
||||
if container.lootContainer then
|
||||
TargetBot.Looting.lootContainer(lootContainers, container)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local dist = math.max(math.abs(pos.x-loot.pos.x), math.abs(pos.y-loot.pos.y))
|
||||
local maxRange = storage.extras.looting or 40
|
||||
if loot.tries > 30 or loot.pos.z ~= pos.z or dist > maxRange then
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
return true
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(loot.pos)
|
||||
if dist >= 3 or not tile then
|
||||
loot.tries = loot.tries + 1
|
||||
TargetBot.walkTo(loot.pos, 20, { ignoreNonPathable = true, precision = 2 })
|
||||
return true
|
||||
end
|
||||
|
||||
local container = tile:getTopUseThing()
|
||||
if not container or not container:isContainer() then
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
return true
|
||||
end
|
||||
|
||||
g_game.open(container)
|
||||
waitTill = now + (storage.extras.lootDelay or 200)
|
||||
waitingForContainer = container:getId()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
TargetBot.Looting.getLootContainers = function(containers)
|
||||
local lootContainers = {}
|
||||
local openedContainersById = {}
|
||||
local toOpen = nil
|
||||
for index, container in pairs(containers) do
|
||||
openedContainersById[container:getContainerItem():getId()] = 1
|
||||
if containersById[container:getContainerItem():getId()] and not container.lootContainer then
|
||||
if container:getItemsCount() < container:getCapacity() or container:hasPages() then
|
||||
table.insert(lootContainers, container)
|
||||
else -- it's full, open next container if possible
|
||||
for slot, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and containersById[item:getId()] then
|
||||
toOpen = {item, container}
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not lootContainers[1] then
|
||||
if toOpen then
|
||||
g_game.open(toOpen[1], toOpen[2])
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
-- check containers one more time, maybe there's any loot container
|
||||
for index, container in pairs(containers) do
|
||||
if not containersById[container:getContainerItem():getId()] and not container.lootContainer then
|
||||
for slot, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and containersById[item:getId()] then
|
||||
g_game.open(item)
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- can't find any lootContainer, let's check slots, maybe there's one
|
||||
for slot = InventorySlotFirst, InventorySlotLast do
|
||||
local item = getInventoryItem(slot)
|
||||
if item and item:isContainer() and not openedContainersById[item:getId()] then
|
||||
-- container which is not opened yet, let's open it
|
||||
g_game.open(item)
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
end
|
||||
end
|
||||
return lootContainers
|
||||
end
|
||||
|
||||
TargetBot.Looting.lootContainer = function(lootContainers, container)
|
||||
-- loot items
|
||||
local nextContainer = nil
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and not itemsById[item:getId()] then
|
||||
nextContainer = item
|
||||
elseif itemsById[item:getId()] or (ui.everyItem:isOn() and not item:isContainer()) then
|
||||
item.lootTries = (item.lootTries or 0) + 1
|
||||
if item.lootTries < 5 then -- if can't be looted within 0.5s then skip it
|
||||
return TargetBot.Looting.lootItem(lootContainers, item)
|
||||
end
|
||||
elseif storage.foodItems and storage.foodItems[1] and lastFoodConsumption + 5000 < now then
|
||||
for _, food in ipairs(storage.foodItems) do
|
||||
if item:getId() == food.id then
|
||||
g_game.use(item)
|
||||
lastFoodConsumption = now
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- no more items to loot, open next container
|
||||
if nextContainer then
|
||||
nextContainer.lootTries = (nextContainer.lootTries or 0) + 1
|
||||
if nextContainer.lootTries < 2 then -- max 0.6s to open it
|
||||
g_game.open(nextContainer, container)
|
||||
waitTill = now + 300 -- give it 0.3s to open
|
||||
waitingForContainer = nextContainer:getId()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- looting finished, remove container from list
|
||||
container.lootContainer = false
|
||||
g_game.close(container)
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if TargetBot.isOff() then return end
|
||||
if #TargetBot.Looting.list == 0 then return end
|
||||
if string.find(text:lower(), "you are not the owner") then -- if we are not the owners of corpse then its a waste of time to try to loot it
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
end
|
||||
end)
|
||||
|
||||
TargetBot.Looting.lootItem = function(lootContainers, item)
|
||||
if item:isStackable() then
|
||||
local count = item:getCount()
|
||||
for _, container in ipairs(lootContainers) do
|
||||
for slot, citem in ipairs(container:getItems()) do
|
||||
if item:getId() == citem:getId() and citem:getCount() < 100 then
|
||||
g_game.move(item, container:getSlotPosition(slot - 1), count)
|
||||
waitTill = now + 300 -- give it 0.3s to move item
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local container = lootContainers[1]
|
||||
g_game.move(item, container:getSlotPosition(container:getItemsCount()), 1)
|
||||
waitTill = now + 300 -- give it 0.3s to move item
|
||||
end
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
if container:getContainerItem():getId() == waitingForContainer then
|
||||
container.lootContainer = true
|
||||
waitingForContainer = nil
|
||||
end
|
||||
end)
|
||||
|
||||
onCreatureDisappear(function(creature)
|
||||
if isInPz() then return end
|
||||
if not TargetBot.isOn() then return end
|
||||
if not creature:isMonster() then return end
|
||||
local config = TargetBot.Creature.calculateParams(creature, {}) -- return {craeture, config, danger, priority}
|
||||
if not config.config or config.config.dontLoot then
|
||||
return
|
||||
end
|
||||
local pos = player:getPosition()
|
||||
local mpos = creature:getPosition()
|
||||
local name = creature:getName()
|
||||
if pos.z ~= mpos.z or math.max(math.abs(pos.x-mpos.x), math.abs(pos.y-mpos.y)) > 6 then return end
|
||||
schedule(20, function() -- check in 20ms if there's container (dead body) on that tile
|
||||
if not containers[1] then return end
|
||||
if TargetBot.Looting.list[20] then return end -- too many items to loot
|
||||
local tile = g_map.getTile(mpos)
|
||||
if not tile then return end
|
||||
local container = tile:getTopUseThing()
|
||||
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)
|
@ -0,0 +1,69 @@
|
||||
TargetBotLootingPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
margin-top: 5
|
||||
text: Items to loot
|
||||
text-align: center
|
||||
|
||||
BotContainer
|
||||
id: items
|
||||
margin-top: 3
|
||||
|
||||
BotSwitch
|
||||
id: everyItem
|
||||
!text: tr("Loot every item")
|
||||
margin-top: 2
|
||||
|
||||
Label
|
||||
margin-top: 5
|
||||
text: Containers for loot
|
||||
text-align: center
|
||||
|
||||
BotContainer
|
||||
id: containers
|
||||
margin-top: 3
|
||||
height: 45
|
||||
|
||||
Panel
|
||||
id: maxDangerPanel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 6
|
||||
width: 80
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Max. danger:
|
||||
margin-left: 5
|
||||
|
||||
Panel
|
||||
id: minCapacityPanel
|
||||
height: 20
|
||||
margin-top: 3
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 6
|
||||
width: 80
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Min. capacity:
|
||||
margin-left: 5
|
328
modules/game_bot/default_configs/vBot_4.8/targetbot/target.lua
Normal file
@ -0,0 +1,328 @@
|
||||
local targetbotMacro = nil
|
||||
local config = nil
|
||||
local lastAction = 0
|
||||
local cavebotAllowance = 0
|
||||
local lureEnabled = true
|
||||
local dangerValue = 0
|
||||
local looterStatus = ""
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
local ui = UI.createWidget("TargetBotPanel")
|
||||
|
||||
ui.list = ui.listPanel.list -- shortcut
|
||||
TargetBot.targetList = ui.list
|
||||
TargetBot.Looting.setup()
|
||||
|
||||
ui.status.left:setText("Status:")
|
||||
ui.status.right:setText("Off")
|
||||
ui.target.left:setText("Target:")
|
||||
ui.target.right:setText("-")
|
||||
ui.config.left:setText("Config:")
|
||||
ui.config.right:setText("-")
|
||||
ui.danger.left:setText("Danger:")
|
||||
ui.danger.right:setText("0")
|
||||
|
||||
ui.editor.debug.onClick = function()
|
||||
local on = ui.editor.debug:isOn()
|
||||
ui.editor.debug:setOn(not on)
|
||||
if on then
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
spec:clearText()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local oldTibia = g_game.getClientVersion() < 960
|
||||
|
||||
-- main loop, controlled by config
|
||||
targetbotMacro = macro(100, function()
|
||||
local pos = player:getPosition()
|
||||
local specs = g_map.getSpectatorsInRange(pos, false, 6, 6) -- 12x12 area
|
||||
local creatures = 0
|
||||
for i, spec in ipairs(specs) do
|
||||
if spec:isMonster() then
|
||||
creatures = creatures + 1
|
||||
end
|
||||
end
|
||||
if creatures > 10 then -- if there are too many monsters around, limit area
|
||||
creatures = g_map.getSpectatorsInRange(pos, false, 3, 3) -- 6x6 area
|
||||
else
|
||||
creatures = specs
|
||||
end
|
||||
local highestPriority = 0
|
||||
local dangerLevel = 0
|
||||
local targets = 0
|
||||
local highestPriorityParams = nil
|
||||
for i, creature in ipairs(creatures) do
|
||||
local hppc = creature:getHealthPercent()
|
||||
if hppc and hppc > 0 then
|
||||
local path = findPath(player:getPosition(), creature:getPosition(), 7, {ignoreLastCreature=true, ignoreNonPathable=true, ignoreCost=true, ignoreCreatures=true})
|
||||
if creature:isMonster() and (oldTibia or creature:getType() < 3) and path then
|
||||
local params = TargetBot.Creature.calculateParams(creature, path) -- return {craeture, config, danger, priority}
|
||||
dangerLevel = dangerLevel + params.danger
|
||||
if params.priority > 0 then
|
||||
targets = targets + 1
|
||||
if params.priority > highestPriority then
|
||||
highestPriority = params.priority
|
||||
highestPriorityParams = params
|
||||
end
|
||||
if ui.editor.debug:isOn() then
|
||||
creature:setText(params.config.name .. "\n" .. params.priority)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- reset walking
|
||||
TargetBot.walkTo(nil)
|
||||
|
||||
-- looting
|
||||
local looting = TargetBot.Looting.process(targets, dangerLevel)
|
||||
local lootingStatus = TargetBot.Looting.getStatus()
|
||||
looterStatus = TargetBot.Looting.getStatus()
|
||||
dangerValue = dangerLevel
|
||||
|
||||
ui.danger.right:setText(dangerLevel)
|
||||
if highestPriorityParams and not isInPz() then
|
||||
ui.target.right:setText(highestPriorityParams.creature:getName())
|
||||
ui.config.right:setText(highestPriorityParams.config.name)
|
||||
TargetBot.Creature.attack(highestPriorityParams, targets, looting)
|
||||
if lootingStatus:len() > 0 then
|
||||
TargetBot.setStatus("Attack & " .. lootingStatus)
|
||||
elseif cavebotAllowance > now then
|
||||
TargetBot.setStatus("Luring using CaveBot")
|
||||
else
|
||||
TargetBot.setStatus("Attacking")
|
||||
if not lureEnabled then
|
||||
TargetBot.setStatus("Attacking (luring off)")
|
||||
end
|
||||
end
|
||||
TargetBot.walk()
|
||||
lastAction = now
|
||||
return
|
||||
end
|
||||
|
||||
ui.target.right:setText("-")
|
||||
ui.config.right:setText("-")
|
||||
if looting then
|
||||
TargetBot.walk()
|
||||
lastAction = now
|
||||
end
|
||||
if lootingStatus:len() > 0 then
|
||||
TargetBot.setStatus(lootingStatus)
|
||||
else
|
||||
TargetBot.setStatus("Waiting")
|
||||
end
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
config = Config.setup("targetbot_configs", configWidget, "json", function(name, enabled, data)
|
||||
if not data then
|
||||
ui.status.right:setText("Off")
|
||||
return targetbotMacro.setOff()
|
||||
end
|
||||
TargetBot.Creature.resetConfigs()
|
||||
for _, value in ipairs(data["targeting"] or {}) do
|
||||
TargetBot.Creature.addConfig(value)
|
||||
end
|
||||
TargetBot.Looting.update(data["looting"] or {})
|
||||
|
||||
-- add configs
|
||||
if enabled then
|
||||
ui.status.right:setText("On")
|
||||
else
|
||||
ui.status.right:setText("Off")
|
||||
end
|
||||
|
||||
targetbotMacro.setOn(enabled)
|
||||
targetbotMacro.delay = nil
|
||||
lureEnabled = true
|
||||
end)
|
||||
|
||||
-- setup ui
|
||||
ui.editor.buttons.add.onClick = function()
|
||||
TargetBot.Creature.edit(nil, function(newConfig)
|
||||
TargetBot.Creature.addConfig(newConfig, true)
|
||||
TargetBot.save()
|
||||
end)
|
||||
end
|
||||
|
||||
ui.editor.buttons.edit.onClick = function()
|
||||
local entry = ui.list:getFocusedChild()
|
||||
if not entry then return end
|
||||
TargetBot.Creature.edit(entry.value, function(newConfig)
|
||||
entry:setText(newConfig.name)
|
||||
entry.value = newConfig
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end)
|
||||
end
|
||||
|
||||
ui.editor.buttons.remove.onClick = function()
|
||||
local entry = ui.list:getFocusedChild()
|
||||
if not entry then return end
|
||||
entry:destroy()
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end
|
||||
|
||||
-- public function, you can use them in your scripts
|
||||
TargetBot.isActive = function() -- return true if attacking or looting takes place
|
||||
return lastAction + 300 > now
|
||||
end
|
||||
|
||||
TargetBot.isCaveBotActionAllowed = function()
|
||||
return cavebotAllowance > now
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
TargetBot.isOff = function()
|
||||
return config.isOff()
|
||||
end
|
||||
|
||||
TargetBot.setOn = function(val)
|
||||
if val == false then
|
||||
return TargetBot.setOff(true)
|
||||
end
|
||||
config.setOn()
|
||||
end
|
||||
|
||||
TargetBot.setOff = function(val)
|
||||
if val == false then
|
||||
return TargetBot.setOn(true)
|
||||
end
|
||||
config.setOff()
|
||||
end
|
||||
|
||||
TargetBot.getCurrentProfile = function()
|
||||
return storage._configs.targetbot_configs.selected
|
||||
end
|
||||
|
||||
local botConfigName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
TargetBot.setCurrentProfile = function(name)
|
||||
if not g_resources.fileExists("/bot/"..botConfigName.."/targetbot_configs/"..name..".json") then
|
||||
return warn("there is no targetbot profile with that name!")
|
||||
end
|
||||
TargetBot.setOff()
|
||||
storage._configs.targetbot_configs.selected = name
|
||||
TargetBot.setOn()
|
||||
end
|
||||
|
||||
TargetBot.delay = function(value)
|
||||
targetbotMacro.delay = now + value
|
||||
end
|
||||
|
||||
TargetBot.save = function()
|
||||
local data = {targeting={}, looting={}}
|
||||
for _, entry in ipairs(ui.list:getChildren()) do
|
||||
table.insert(data.targeting, entry.value)
|
||||
end
|
||||
TargetBot.Looting.save(data.looting)
|
||||
config.save(data)
|
||||
end
|
||||
|
||||
TargetBot.allowCaveBot = function(time)
|
||||
cavebotAllowance = now + time
|
||||
end
|
||||
|
||||
TargetBot.disableLuring = function()
|
||||
lureEnabled = false
|
||||
end
|
||||
|
||||
TargetBot.enableLuring = function()
|
||||
lureEnabled = true
|
||||
end
|
||||
|
||||
TargetBot.Danger = function()
|
||||
return dangerValue
|
||||
end
|
||||
|
||||
TargetBot.lootStatus = function()
|
||||
return looterStatus
|
||||
end
|
||||
|
||||
|
||||
-- attacks
|
||||
local lastSpell = 0
|
||||
local lastAttackSpell = 0
|
||||
|
||||
TargetBot.saySpell = function(text, delay)
|
||||
if type(text) ~= 'string' or text:len() < 1 then return end
|
||||
if not delay then delay = 500 end
|
||||
if g_game.getProtocolVersion() < 1090 then
|
||||
lastAttackSpell = now -- pause attack spells, healing spells are more important
|
||||
end
|
||||
if lastSpell + delay < now then
|
||||
say(text)
|
||||
lastSpell = now
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
TargetBot.sayAttackSpell = function(text, delay)
|
||||
if type(text) ~= 'string' or text:len() < 1 then return end
|
||||
if not delay then delay = 2000 end
|
||||
if lastAttackSpell + delay < now then
|
||||
say(text)
|
||||
lastAttackSpell = now
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local lastItemUse = 0
|
||||
local lastRuneAttack = 0
|
||||
|
||||
TargetBot.useItem = function(item, subType, target, delay)
|
||||
if not delay then delay = 200 end
|
||||
if lastItemUse + delay < now then
|
||||
local thing = g_things.getThingType(item)
|
||||
if not thing or not thing:isFluidContainer() then
|
||||
subType = g_game.getClientVersion() >= 860 and 0 or 1
|
||||
end
|
||||
if g_game.getClientVersion() < 780 then
|
||||
local tmpItem = g_game.findPlayerItem(item, subType)
|
||||
if not tmpItem then return end
|
||||
g_game.useWith(tmpItem, target, subType) -- using item from bp
|
||||
else
|
||||
g_game.useInventoryItemWith(item, target, subType) -- hotkey
|
||||
end
|
||||
lastItemUse = now
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.useAttackItem = function(item, subType, target, delay)
|
||||
if not delay then delay = 2000 end
|
||||
if lastRuneAttack + delay < now then
|
||||
local thing = g_things.getThingType(item)
|
||||
if not thing or not thing:isFluidContainer() then
|
||||
subType = g_game.getClientVersion() >= 860 and 0 or 1
|
||||
end
|
||||
if g_game.getClientVersion() < 780 then
|
||||
local tmpItem = g_game.findPlayerItem(item, subType)
|
||||
if not tmpItem then return end
|
||||
g_game.useWith(tmpItem, target, subType) -- using item from bp
|
||||
else
|
||||
g_game.useInventoryItemWith(item, target, subType) -- hotkey
|
||||
end
|
||||
lastRuneAttack = now
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.canLure = function()
|
||||
return lureEnabled
|
||||
end
|
115
modules/game_bot/default_configs/vBot_4.8/targetbot/target.otui
Normal file
@ -0,0 +1,115 @@
|
||||
TargetBotEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
TargetBotDualLabel < Panel
|
||||
height: 18
|
||||
margin-left: 3
|
||||
margin-right: 4
|
||||
|
||||
Label
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-auto-resize: true
|
||||
|
||||
Label
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
text-auto-resize: true
|
||||
|
||||
TargetBotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 2
|
||||
margin-bottom: 5
|
||||
|
||||
TargetBotDualLabel
|
||||
id: status
|
||||
TargetBotDualLabel
|
||||
id: target
|
||||
TargetBotDualLabel
|
||||
id: config
|
||||
TargetBotDualLabel
|
||||
id: danger
|
||||
|
||||
Panel
|
||||
id: listPanel
|
||||
height: 40
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: listScrollbar
|
||||
margin-right: 15
|
||||
focusable: false
|
||||
auto-focus: first
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollbar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
pixels-scroll: true
|
||||
step: 10
|
||||
|
||||
BotSwitch
|
||||
id: configButton
|
||||
@onClick: |
|
||||
self:setOn(not self:isOn())
|
||||
self:getParent().listPanel:setHeight(self:isOn() and 100 or 40)
|
||||
self:getParent().editor:setVisible(self:isOn())
|
||||
|
||||
$on:
|
||||
text: Hide target editor
|
||||
|
||||
$!on:
|
||||
text: Show target editor
|
||||
|
||||
Panel
|
||||
id: editor
|
||||
visible: false
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
height: 20
|
||||
margin-top: 2
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
text: Add
|
||||
width: 56
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: Edit
|
||||
width: 56
|
||||
|
||||
Button
|
||||
id: remove
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
text: Remove
|
||||
width: 56
|
||||
|
||||
BotSwitch
|
||||
id: debug
|
||||
text: Show target priority
|
@ -0,0 +1,28 @@
|
||||
local dest
|
||||
local maxDist
|
||||
local params
|
||||
|
||||
TargetBot.walkTo = function(_dest, _maxDist, _params)
|
||||
dest = _dest
|
||||
maxDist = _maxDist
|
||||
params = _params
|
||||
end
|
||||
|
||||
-- called every 100ms if targeting or looting is active
|
||||
TargetBot.walk = function()
|
||||
if not dest then return end
|
||||
if player:isWalking() then return end
|
||||
local pos = player:getPosition()
|
||||
if pos.z ~= dest.z then return end
|
||||
local dist = math.max(math.abs(pos.x-dest.x), math.abs(pos.y-dest.y))
|
||||
if params.precision and params.precision >= dist then return end
|
||||
if params.marginMin and params.marginMax then
|
||||
if dist >= params.marginMin and dist <= params.marginMax then
|
||||
return
|
||||
end
|
||||
end
|
||||
local path = getPath(pos, dest, maxDist, params)
|
||||
if path then
|
||||
walk(path[1])
|
||||
end
|
||||
end
|
1254
modules/game_bot/default_configs/vBot_4.8/vBot/AttackBot.lua
Normal file
624
modules/game_bot/default_configs/vBot_4.8/vBot/AttackBot.otui
Normal file
@ -0,0 +1,624 @@
|
||||
AttackEntry < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 35 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
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
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
AttackBotBotPanel < Panel
|
||||
height: 38
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('AttackBot')
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
Button
|
||||
id: 1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text: 1
|
||||
margin-right: 2
|
||||
margin-top: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 2
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 2
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 3
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 3
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 4
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 5
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Label
|
||||
id: name
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-left: 4
|
||||
height: 17
|
||||
text: Profile #1
|
||||
background: #292A2A
|
||||
|
||||
CategoryLabel < Panel
|
||||
size: 315 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: Area Rune (avalanche, great fireball, etc)
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
SourceLabel < Panel
|
||||
size: 105 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: Monster Name
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
RangeLabel < Panel
|
||||
size: 323 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: 5 Sqm
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
PreButton < PreviousButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
NexButton < NextButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
AttackBotPanel < Panel
|
||||
size: 500 200
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 5
|
||||
|
||||
TextList
|
||||
id: entryList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 3
|
||||
size: 430 100
|
||||
vertical-scrollbar: entryListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: entryListScrollBar
|
||||
anchors.top: entryList.top
|
||||
anchors.bottom: entryList.bottom
|
||||
anchors.right: entryList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
PreButton
|
||||
id: previousCategory
|
||||
anchors.left: entryList.left
|
||||
anchors.top: entryList.bottom
|
||||
margin-top: 8
|
||||
|
||||
NexButton
|
||||
id: nextCategory
|
||||
anchors.left: category.right
|
||||
anchors.top: entryList.bottom
|
||||
margin-top: 8
|
||||
margin-left: 2
|
||||
|
||||
CategoryLabel
|
||||
id: category
|
||||
anchors.top: entryList.bottom
|
||||
anchors.left: previousCategory.right
|
||||
anchors.verticalCenter: previousCategory.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
PreButton
|
||||
id: previousSource
|
||||
anchors.left: entryList.left
|
||||
anchors.top: category.bottom
|
||||
margin-top: 8
|
||||
|
||||
NexButton
|
||||
id: nextSource
|
||||
anchors.left: source.right
|
||||
anchors.top: category.bottom
|
||||
margin-top: 8
|
||||
margin-left: 2
|
||||
|
||||
SourceLabel
|
||||
id: source
|
||||
anchors.top: category.bottom
|
||||
anchors.left: previousSource.right
|
||||
anchors.verticalCenter: previousSource.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
PreButton
|
||||
id: previousRange
|
||||
anchors.left: nextSource.right
|
||||
anchors.verticalCenter: nextSource.verticalCenter
|
||||
margin-left: 8
|
||||
|
||||
NexButton
|
||||
id: nextRange
|
||||
anchors.left: range.right
|
||||
anchors.verticalCenter: range.verticalCenter
|
||||
margin-left: 2
|
||||
|
||||
RangeLabel
|
||||
id: range
|
||||
anchors.left: previousRange.right
|
||||
anchors.verticalCenter: previousRange.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
TextEdit
|
||||
id: monsters
|
||||
anchors.left: entryList.left
|
||||
anchors.top: range.bottom
|
||||
margin-top: 5
|
||||
size: 405 15
|
||||
text: monster names
|
||||
font: cipsoftFont
|
||||
background: #363636
|
||||
|
||||
Label
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 6
|
||||
margin-left: 3
|
||||
text-align: center
|
||||
text: Mana%:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: manaPercent
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 30 20
|
||||
minimum: 0
|
||||
maximum: 99
|
||||
step: 1
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Creatures:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: creatures
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 30 20
|
||||
minimum: 1
|
||||
maximum: 99
|
||||
step: 1
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
CheckBox
|
||||
id: orMore
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
tooltip: or more creatures
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: HP:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: minHp
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 40 20
|
||||
minimum: 0
|
||||
maximum: 99
|
||||
value: 0
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: -
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: maxHp
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 40 20
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
value: 100
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: CD:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: cooldown
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 60 20
|
||||
minimum: 0
|
||||
maximum: 999999
|
||||
step: 100
|
||||
value: 0
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Button
|
||||
id: up
|
||||
anchors.right: parent.right
|
||||
anchors.top: entryList.bottom
|
||||
size: 60 17
|
||||
text: Move Up
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
margin-top: 7
|
||||
margin-right: 8
|
||||
|
||||
Button
|
||||
id: down
|
||||
anchors.right: prev.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 60 17
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: addEntry
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 40 19
|
||||
text-align: center
|
||||
text: New
|
||||
font: cipsoftFont
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.right: addEntry.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
tooltip: drag item here on press to open window
|
||||
|
||||
TextEdit
|
||||
id: spellName
|
||||
anchors.top: monsters.top
|
||||
anchors.left: monsters.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
height: 15
|
||||
text: spell name
|
||||
background: #363636
|
||||
font: cipsoftFont
|
||||
visible: false
|
||||
|
||||
SettingsPanel < Panel
|
||||
size: 500 200
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 10
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: Visible.right
|
||||
margin-left: 10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 10
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: Profile:
|
||||
|
||||
TextEdit
|
||||
id: profileName
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
margin-left: 20
|
||||
margin-right: 20
|
||||
|
||||
Button
|
||||
id: resetSettings
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
text-align: center
|
||||
text: Reset Settings
|
||||
|
||||
CheckBox
|
||||
id: IgnoreMana
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 5
|
||||
width: 200
|
||||
text: Check RL Tibia conditions
|
||||
|
||||
CheckBox
|
||||
id: Kills
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 200
|
||||
height: 22
|
||||
text: Don't use area attacks if less than kills to red skull
|
||||
text-wrap: true
|
||||
text-align: left
|
||||
|
||||
SpinBox
|
||||
id: KillsAmount
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
text-align: left
|
||||
width: 30
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
focusable: true
|
||||
margin-left: 5
|
||||
|
||||
CheckBox
|
||||
id: Rotate
|
||||
anchors.top: Kills.bottom
|
||||
anchors.left: Kills.left
|
||||
margin-top: 8
|
||||
width: 220
|
||||
text: Turn to side with most monsters
|
||||
|
||||
CheckBox
|
||||
id: Cooldown
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 220
|
||||
text: Check spell cooldowns
|
||||
|
||||
CheckBox
|
||||
id: Visible
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: Items must be visible (recommended)
|
||||
|
||||
CheckBox
|
||||
id: PvpMode
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: PVP mode
|
||||
|
||||
CheckBox
|
||||
id: PvpSafe
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: PVP safe
|
||||
|
||||
CheckBox
|
||||
id: Training
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: Stop when attacking trainers
|
||||
|
||||
CheckBox
|
||||
id: BlackListSafe
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 200
|
||||
height: 18
|
||||
text: Stop if Anti-RS player in range
|
||||
|
||||
SpinBox
|
||||
id: AntiRsRange
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
text-align: center
|
||||
width: 50
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
focusable: true
|
||||
margin-left: 5
|
||||
|
||||
AttackBotWindow < MainWindow
|
||||
size: 535 300
|
||||
padding: 15
|
||||
text: AttackBot v2
|
||||
@onEscape: self:hide()
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 10
|
||||
margin-left: 2
|
||||
!text: tr('More important methods come first (Example: Exori gran above Exori)')
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
SettingsPanel
|
||||
id: settingsPanel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
margin-left: 2
|
||||
|
||||
Label
|
||||
id: settingsLabel
|
||||
anchors.verticalCenter: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-left: 3
|
||||
text: Settings
|
||||
color: #fe4400
|
||||
font: verdana-11px-rounded
|
||||
|
||||
AttackBotPanel
|
||||
id: mainPanel
|
||||
anchors.top: mainLabel.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
margin-left: 2
|
||||
visible: false
|
||||
|
||||
Label
|
||||
id: shooterLabel
|
||||
anchors.verticalCenter: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-left: 3
|
||||
text: Spell Shooter
|
||||
color: #fe4400
|
||||
font: verdana-11px-rounded
|
||||
visible: false
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 10
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
text: Close
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 50 21
|
||||
font: cipsoftFont
|
||||
text: Settings
|
244
modules/game_bot/default_configs/vBot_4.8/vBot/BotServer.lua
Normal file
@ -0,0 +1,244 @@
|
||||
setDefaultTab("Main")
|
||||
local regex = [["(.*?)"]]
|
||||
local panelName = "BOTserver"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 18
|
||||
|
||||
Button
|
||||
id: botServer
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
height: 18
|
||||
!text: tr('BotServer')
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
manaInfo = true,
|
||||
mwallInfo = true,
|
||||
vocation = true,
|
||||
outfit = false,
|
||||
broadcasts = true
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
config.mwalls = {}
|
||||
|
||||
if not storage.BotServerChannel then
|
||||
math.randomseed(os.time())
|
||||
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
|
||||
end
|
||||
|
||||
local channel = tostring(storage.BotServerChannel)
|
||||
if config.enabled then
|
||||
BotServer.init(name(), channel)
|
||||
end
|
||||
|
||||
vBot.BotServerMembers = {}
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
botServerWindow = UI.createWindow('BotServerWindow')
|
||||
botServerWindow:hide()
|
||||
|
||||
|
||||
botServerWindow.enabled:setOn(config.enabled)
|
||||
botServerWindow.enabled.onClick = function()
|
||||
config.enabled = not config.enabled
|
||||
botServerWindow.enabled:setOn(config.enabled)
|
||||
if config.enabled then
|
||||
channel = tostring(storage.BotServerChannel)
|
||||
BotServer.init(name(), channel)
|
||||
botServerWindow.Data.ServerStatus:setText("CONNECTING...")
|
||||
ui.botServer:setColor('#FFF380')
|
||||
botServerWindow.Data.ServerStatus:setColor('#FFF380')
|
||||
else
|
||||
if BotServer._websocket then
|
||||
BotServer.terminate()
|
||||
end
|
||||
botServerWindow.Data.ServerStatus:setText("DISCONNECTED")
|
||||
ui.botServer:setColor('#E3242B')
|
||||
botServerWindow.Data.ServerStatus:setColor('#E3242B')
|
||||
botServerWindow.Data.Participants:setText("-")
|
||||
botServerWindow.Data.Members:setTooltip('')
|
||||
ServerMembers = {}
|
||||
serverCount = {}
|
||||
end
|
||||
initBotServerListenFunctions()
|
||||
schedule(2000, updateStatusText)
|
||||
end
|
||||
|
||||
botServerWindow.Data.Channel:setText(storage.BotServerChannel)
|
||||
botServerWindow.Data.Channel.onTextChange = function(widget, text)
|
||||
storage.BotServerChannel = text
|
||||
end
|
||||
botServerWindow.Data.Random.onClick = function(widget)
|
||||
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
|
||||
botServerWindow.Data.Channel:setText(storage.BotServerChannel)
|
||||
end
|
||||
botServerWindow.Features.Feature1:setOn(config.manaInfo)
|
||||
botServerWindow.Features.Feature1.onClick = function(widget)
|
||||
config.manaInfo = not config.manaInfo
|
||||
widget:setOn(config.manaInfo)
|
||||
end
|
||||
botServerWindow.Features.Feature2:setOn(config.mwallInfo)
|
||||
botServerWindow.Features.Feature2.onClick = function(widget)
|
||||
config.mwallInfo = not config.mwallInfo
|
||||
widget:setOn(config.mwallInfo)
|
||||
end
|
||||
botServerWindow.Features.Feature3:setOn(config.vocation)
|
||||
botServerWindow.Features.Feature3.onClick = function(widget)
|
||||
config.vocation = not config.vocation
|
||||
if config.vocation then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
end
|
||||
widget:setOn(config.vocation)
|
||||
end
|
||||
botServerWindow.Features.Feature4:setOn(config.outfit)
|
||||
botServerWindow.Features.Feature4.onClick = function(widget)
|
||||
config.outfit = not config.outfit
|
||||
widget:setOn(config.outfit)
|
||||
end
|
||||
botServerWindow.Features.Feature5:setOn(config.broadcasts)
|
||||
botServerWindow.Features.Feature5.onClick = function(widget)
|
||||
config.broadcasts = not config.broadcasts
|
||||
widget:setOn(config.broadcasts)
|
||||
end
|
||||
botServerWindow.Features.Broadcast.onClick = function(widget)
|
||||
if BotServer._websocket then
|
||||
BotServer.send("broadcast", botServerWindow.Features.broadcastText:getText())
|
||||
end
|
||||
botServerWindow.Features.broadcastText:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
function initBotServerListenFunctions()
|
||||
if not BotServer._websocket then return end
|
||||
if not config.enabled then return end
|
||||
|
||||
-- list
|
||||
BotServer.listen("list", function(name, data)
|
||||
serverCount = regexMatch(json.encode(data), regex)
|
||||
ServerMembers = json.encode(data)
|
||||
end)
|
||||
|
||||
-- mwalls
|
||||
BotServer.listen("mwall", function(name, message)
|
||||
if config.mwallInfo then
|
||||
if not config.mwalls[message["pos"]] or config.mwalls[message["pos"]] < now then
|
||||
config.mwalls[message["pos"]] = now + message["duration"] - 150 -- 150 is latency correction
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- mana
|
||||
BotServer.listen("mana", function(name, message)
|
||||
if config.manaInfo then
|
||||
local creature = getPlayerByName(name)
|
||||
if creature then
|
||||
creature:setManaPercent(message["mana"])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- vocation
|
||||
BotServer.listen("voc", function(name, message)
|
||||
if message == "yes" and config.vocation then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
else
|
||||
vBot.BotServerMembers[name] = message
|
||||
end
|
||||
end)
|
||||
|
||||
-- broadcast
|
||||
BotServer.listen("broadcast", function(name, message)
|
||||
if config.broadcasts then
|
||||
broadcastMessage(name..": "..message)
|
||||
end
|
||||
end)
|
||||
end
|
||||
initBotServerListenFunctions()
|
||||
|
||||
function updateStatusText()
|
||||
if BotServer._websocket then
|
||||
botServerWindow.Data.ServerStatus:setText("CONNECTED")
|
||||
botServerWindow.Data.ServerStatus:setColor('#03AC13')
|
||||
ui.botServer:setColor('#03AC13')
|
||||
if serverCount then
|
||||
botServerWindow.Data.Participants:setText(#serverCount)
|
||||
if ServerMembers then
|
||||
local text = ""
|
||||
local regex = [["([a-z 'A-z-]*)"*]]
|
||||
local re = regexMatch(ServerMembers, regex)
|
||||
--re[name][2]
|
||||
for i=1,#re do
|
||||
if i == 1 then
|
||||
text = re[i][2]
|
||||
else
|
||||
text = text .. "\n" .. re[i][2]
|
||||
end
|
||||
end
|
||||
botServerWindow.Data.Members:setTooltip(text)
|
||||
end
|
||||
end
|
||||
else
|
||||
botServerWindow.Data.ServerStatus:setText("DISCONNECTED")
|
||||
ui.botServer:setColor('#E3242B')
|
||||
botServerWindow.Data.ServerStatus:setColor('#E3242B')
|
||||
botServerWindow.Data.Participants:setText("-")
|
||||
end
|
||||
end
|
||||
|
||||
macro(1000, function()
|
||||
if BotServer._websocket then
|
||||
BotServer.send("list")
|
||||
end
|
||||
updateStatusText()
|
||||
delay(9000)
|
||||
end)
|
||||
|
||||
ui.botServer.onClick = function(widget)
|
||||
botServerWindow:show()
|
||||
botServerWindow:raise()
|
||||
botServerWindow:focus()
|
||||
end
|
||||
|
||||
botServerWindow.closeButton.onClick = function(widget)
|
||||
botServerWindow:hide()
|
||||
end
|
||||
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if config.mwallInfo and BotServer._websocket then
|
||||
if thing:isItem() and thing:getId() == 2129 then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not config.mwalls[pos] or config.mwalls[pos] < now then
|
||||
config.mwalls[pos] = now + 20000
|
||||
BotServer.send("mwall", {pos=pos, duration=20000})
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- mana
|
||||
local lastMana = 0
|
||||
macro(500, function()
|
||||
if config.manaInfo and BotServer._websocket then
|
||||
if manapercent() ~= lastMana then
|
||||
lastMana = manapercent()
|
||||
BotServer.send("mana", {mana=lastMana})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- vocation
|
||||
if config.vocation and BotServer._websocket then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
BotServer.send("voc", "yes")
|
||||
end
|
||||
|
||||
addSeparator()
|
202
modules/game_bot/default_configs/vBot_4.8/vBot/BotServer.otui
Normal file
@ -0,0 +1,202 @@
|
||||
BotServerData < Panel
|
||||
size: 340 70
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
padding: 3
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
!text: tr("BotServer Data")
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 23
|
||||
text-align: center
|
||||
text: Channel Name:
|
||||
margin-left: 6
|
||||
|
||||
TextEdit
|
||||
id: Channel
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-top: 20
|
||||
width: 150
|
||||
margin-left: 5
|
||||
text-align: center
|
||||
|
||||
Button
|
||||
id: Random
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Randomize
|
||||
margin-left: 6
|
||||
margin-right: 6
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 6
|
||||
margin-bottom: 4
|
||||
text-align: center
|
||||
text: Status:
|
||||
|
||||
Label
|
||||
id: ServerStatus
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 10
|
||||
width: 150
|
||||
margin-bottom: 4
|
||||
text-align: left
|
||||
|
||||
Label
|
||||
id: Participants
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
width: 20
|
||||
margin-right: 8
|
||||
margin-bottom: 4
|
||||
text-align: center
|
||||
|
||||
UIWidget
|
||||
id: Members
|
||||
anchors.right: Participants.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 80 21
|
||||
text-align: center
|
||||
text: Members:
|
||||
|
||||
FeaturePanel < Panel
|
||||
size: 340 150
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 3
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text-align: center
|
||||
text: Features
|
||||
|
||||
HorizontalSeparator
|
||||
id: sep
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
|
||||
BotSwitch
|
||||
id: Feature1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-left: 3
|
||||
margin-top: 5
|
||||
text: Mana info
|
||||
|
||||
BotSwitch
|
||||
id: Feature2
|
||||
anchors.top: sep.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
text: MWall info
|
||||
|
||||
BotSwitch
|
||||
id: Feature3
|
||||
anchors.top: sep.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
text: Send Vocation
|
||||
|
||||
BotSwitch
|
||||
id: Feature4
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
text: Outfit Vocation
|
||||
|
||||
BotSwitch
|
||||
id: Feature5
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Broadcasts
|
||||
|
||||
|
||||
TextEdit
|
||||
id: broadcastText
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
margin-bottom: 3
|
||||
margin-right: 80
|
||||
|
||||
Button
|
||||
id: Broadcast
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
height: 22
|
||||
text: Broadcast
|
||||
|
||||
BotServerWindow < MainWindow
|
||||
!text: tr('BotServer')
|
||||
size: 370 310
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotServerData
|
||||
id: Data
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
FeaturePanel
|
||||
id: Features
|
||||
anchors.top: prev.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 10
|
||||
|
||||
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
|
||||
|
||||
BotSwitch
|
||||
id: enabled
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: parent.left
|
||||
margin-left: 5
|
||||
height: 21
|
||||
|
||||
$!on:
|
||||
text: BotServer: OFF
|
||||
|
||||
$on:
|
||||
text: BotServer: ON
|
262
modules/game_bot/default_configs/vBot_4.8/vBot/Conditions.lua
Normal file
@ -0,0 +1,262 @@
|
||||
setDefaultTab("HP")
|
||||
local panelName = "ConditionPanel"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Conditions')
|
||||
|
||||
Button
|
||||
id: conditionList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not HealBotConfig[panelName] then
|
||||
HealBotConfig[panelName] = {
|
||||
enabled = false,
|
||||
curePosion = false,
|
||||
poisonCost = 20,
|
||||
cureCurse = false,
|
||||
curseCost = 80,
|
||||
cureBleed = false,
|
||||
bleedCost = 45,
|
||||
cureBurn = false,
|
||||
burnCost = 30,
|
||||
cureElectrify = false,
|
||||
electrifyCost = 22,
|
||||
cureParalyse = false,
|
||||
paralyseCost = 40,
|
||||
paralyseSpell = "utani hur",
|
||||
holdHaste = false,
|
||||
hasteCost = 40,
|
||||
hasteSpell = "utani hur",
|
||||
holdUtamo = false,
|
||||
utamoCost = 40,
|
||||
holdUtana = false,
|
||||
utanaCost = 440,
|
||||
holdUtura = false,
|
||||
uturaType = "",
|
||||
uturaCost = 100,
|
||||
ignoreInPz = true,
|
||||
stopHaste = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = HealBotConfig[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
ui.conditionList.onClick = function(widget)
|
||||
conditionsWindow:show()
|
||||
conditionsWindow:raise()
|
||||
conditionsWindow:focus()
|
||||
end
|
||||
|
||||
|
||||
|
||||
local rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
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)
|
||||
config.poisonCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CurseCost:setText(config.curseCost)
|
||||
conditionsWindow.Cure.CurseCost.onTextChange = function(widget, text)
|
||||
config.curseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BleedCost:setText(config.bleedCost)
|
||||
conditionsWindow.Cure.BleedCost.onTextChange = function(widget, text)
|
||||
config.bleedCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BurnCost:setText(config.burnCost)
|
||||
conditionsWindow.Cure.BurnCost.onTextChange = function(widget, text)
|
||||
config.burnCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ElectrifyCost:setText(config.electrifyCost)
|
||||
conditionsWindow.Cure.ElectrifyCost.onTextChange = function(widget, text)
|
||||
config.electrifyCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseCost:setText(config.paralyseCost)
|
||||
conditionsWindow.Cure.ParalyseCost.onTextChange = function(widget, text)
|
||||
config.paralyseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseSpell:setText(config.paralyseSpell)
|
||||
conditionsWindow.Cure.ParalyseSpell.onTextChange = function(widget, text)
|
||||
config.paralyseSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteSpell:setText(config.hasteSpell)
|
||||
conditionsWindow.Hold.HasteSpell.onTextChange = function(widget, text)
|
||||
config.hasteSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteCost:setText(config.hasteCost)
|
||||
conditionsWindow.Hold.HasteCost.onTextChange = function(widget, text)
|
||||
config.hasteCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtamoCost:setText(config.utamoCost)
|
||||
conditionsWindow.Hold.UtamoCost.onTextChange = function(widget, text)
|
||||
config.utamoCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtanaCost:setText(config.utanaCost)
|
||||
conditionsWindow.Hold.UtanaCost.onTextChange = function(widget, text)
|
||||
config.utanaCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UturaCost:setText(config.uturaCost)
|
||||
conditionsWindow.Hold.UturaCost.onTextChange = function(widget, text)
|
||||
config.uturaCost = tonumber(text)
|
||||
end
|
||||
|
||||
-- combo box
|
||||
conditionsWindow.Hold.UturaType:setOption(config.uturaType)
|
||||
conditionsWindow.Hold.UturaType.onOptionChange = function(widget)
|
||||
config.uturaType = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
conditionsWindow.Cure.CurePoison:setChecked(config.curePoison)
|
||||
conditionsWindow.Cure.CurePoison.onClick = function(widget)
|
||||
config.curePoison = not config.curePoison
|
||||
widget:setChecked(config.curePoison)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureCurse:setChecked(config.cureCurse)
|
||||
conditionsWindow.Cure.CureCurse.onClick = function(widget)
|
||||
config.cureCurse = not config.cureCurse
|
||||
widget:setChecked(config.cureCurse)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBleed:setChecked(config.cureBleed)
|
||||
conditionsWindow.Cure.CureBleed.onClick = function(widget)
|
||||
config.cureBleed = not config.cureBleed
|
||||
widget:setChecked(config.cureBleed)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBurn:setChecked(config.cureBurn)
|
||||
conditionsWindow.Cure.CureBurn.onClick = function(widget)
|
||||
config.cureBurn = not config.cureBurn
|
||||
widget:setChecked(config.cureBurn)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureElectrify:setChecked(config.cureElectrify)
|
||||
conditionsWindow.Cure.CureElectrify.onClick = function(widget)
|
||||
config.cureElectrify = not config.cureElectrify
|
||||
widget:setChecked(config.cureElectrify)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureParalyse:setChecked(config.cureParalyse)
|
||||
conditionsWindow.Cure.CureParalyse.onClick = function(widget)
|
||||
config.cureParalyse = not config.cureParalyse
|
||||
widget:setChecked(config.cureParalyse)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldHaste:setChecked(config.holdHaste)
|
||||
conditionsWindow.Hold.HoldHaste.onClick = function(widget)
|
||||
config.holdHaste = not config.holdHaste
|
||||
widget:setChecked(config.holdHaste)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtamo:setChecked(config.holdUtamo)
|
||||
conditionsWindow.Hold.HoldUtamo.onClick = function(widget)
|
||||
config.holdUtamo = not config.holdUtamo
|
||||
widget:setChecked(config.holdUtamo)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtana:setChecked(config.holdUtana)
|
||||
conditionsWindow.Hold.HoldUtana.onClick = function(widget)
|
||||
config.holdUtana = not config.holdUtana
|
||||
widget:setChecked(config.holdUtana)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtura:setChecked(config.holdUtura)
|
||||
conditionsWindow.Hold.HoldUtura.onClick = function(widget)
|
||||
config.holdUtura = not config.holdUtura
|
||||
widget:setChecked(config.holdUtura)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.IgnoreInPz:setChecked(config.ignoreInPz)
|
||||
conditionsWindow.Hold.IgnoreInPz.onClick = function(widget)
|
||||
config.ignoreInPz = not config.ignoreInPz
|
||||
widget:setChecked(config.ignoreInPz)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.StopHaste:setChecked(config.stopHaste)
|
||||
conditionsWindow.Hold.StopHaste.onClick = function(widget)
|
||||
config.stopHaste = not config.stopHaste
|
||||
widget:setChecked(config.stopHaste)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
conditionsWindow.closeButton.onClick = function(widget)
|
||||
conditionsWindow:hide()
|
||||
end
|
||||
|
||||
Conditions = {}
|
||||
Conditions.show = function()
|
||||
conditionsWindow:show()
|
||||
conditionsWindow:raise()
|
||||
conditionsWindow:focus()
|
||||
end
|
||||
end
|
||||
|
||||
local utanaCast = nil
|
||||
macro(500, function()
|
||||
if not config.enabled or modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
if hppercent() > 95 then
|
||||
if config.curePoison and mana() >= config.poisonCost and isPoisioned() then say("exana pox")
|
||||
elseif config.cureCurse and mana() >= config.curseCost and isCursed() then say("exana mort")
|
||||
elseif config.cureBleed and mana() >= config.bleedCost and isBleeding() then say("exana kor")
|
||||
elseif config.cureBurn and mana() >= config.burnCost and isBurning() then say("exana flam")
|
||||
elseif config.cureElectrify and mana() >= config.electrifyCost and isEnergized() then say("exana vis")
|
||||
end
|
||||
end
|
||||
if (not config.ignoreInPz or not isInPz()) and config.holdUtura and mana() >= config.uturaCost and canCast(config.uturaType) and hppercent() < 90 then say(config.uturaType)
|
||||
elseif (not config.ignoreInPz or not isInPz()) and config.holdUtana and mana() >= config.utanaCost and (not utanaCast or (now - utanaCast > 120000)) then say("utana vid") utanaCast = now
|
||||
end
|
||||
end)
|
||||
|
||||
macro(50, function()
|
||||
if not config.enabled then return end
|
||||
if (not config.ignoreInPz or not isInPz()) and config.holdUtamo and mana() >= config.utamoCost and not hasManaShield() then say("utamo vita")
|
||||
elseif ((not config.ignoreInPz or not isInPz()) and standTime() < 5000 and config.holdHaste and mana() >= config.hasteCost and not hasHaste() and not getSpellCoolDown(config.hasteSpell) and (not target() or not config.stopHaste or TargetBot.isCaveBotActionAllowed())) and standTime() < 3000 then say(config.hasteSpell)
|
||||
elseif config.cureParalyse and mana() >= config.paralyseCost and isParalyzed() and not getSpellCoolDown(config.paralyseSpell) then say(config.paralyseSpell)
|
||||
end
|
||||
end)
|
463
modules/game_bot/default_configs/vBot_4.8/vBot/Conditions.otui
Normal file
@ -0,0 +1,463 @@
|
||||
UturaComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
UturaComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
UturaComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Utura")
|
||||
self:addOption("Utura Gran")
|
||||
|
||||
CureConditions < Panel
|
||||
id: Cure
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 200 190
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Poison
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 40
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: PoisonCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CurePoison
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 10
|
||||
text: Curse
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label22
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: CurseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureCurse
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label2.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 10
|
||||
text: Bleed
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 46
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: BleedCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureBleed
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 10
|
||||
text: Burn
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 50
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: BurnCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureBurn
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label5
|
||||
anchors.left: label4.left
|
||||
anchors.top: label4.bottom
|
||||
margin-top: 10
|
||||
text: Electify
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 33
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ElectrifyCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureElectrify
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label6
|
||||
anchors.left: label5.left
|
||||
anchors.top: label5.bottom
|
||||
margin-top: 10
|
||||
text: Paralyse
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label66
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 26
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ParalyseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureParalyse
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label7
|
||||
anchors.left: label6.left
|
||||
anchors.top: label6.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ParalyseSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HoldConditions < Panel
|
||||
id: Hold
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 200 190
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Haste
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: HasteCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldHaste
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: HasteSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label1.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 10
|
||||
text: Utana Vid
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 21
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UtanaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtana
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 10
|
||||
text: Utamo Vita
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 12
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UtamoCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtamo
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label5
|
||||
anchors.left: label4.left
|
||||
anchors.top: label4.bottom
|
||||
margin-top: 10
|
||||
text: Recovery
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 20
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UturaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtura
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label6
|
||||
anchors.left: label5.left
|
||||
anchors.top: label5.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
UturaComboBox
|
||||
id: UturaType
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: IgnoreInPz
|
||||
anchors.left: label5.left
|
||||
anchors.top: label6.bottom
|
||||
margin-top: 12
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: IgnoreInPz.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Don't Cast in Protection Zones
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: StopHaste
|
||||
anchors.horizontalCenter: IgnoreInPz.horizontalCenter
|
||||
anchors.top: IgnoreInPz.bottom
|
||||
margin-top: 8
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Stop Haste if TargetBot Is Active
|
||||
font: cipsoftFont
|
||||
|
||||
ConditionsWindow < MainWindow
|
||||
!text: tr('Condition Manager')
|
||||
size: 445 280
|
||||
@onEscape: self:hide()
|
||||
|
||||
CureConditions
|
||||
id: Cure
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Cure Conditions
|
||||
color: #88e3dd
|
||||
margin-left: 10
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HoldConditions
|
||||
id: Hold
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
text: Hold Conditions
|
||||
color: #88e3dd
|
||||
margin-right: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
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
|
674
modules/game_bot/default_configs/vBot_4.8/vBot/Containers.lua
Normal file
@ -0,0 +1,674 @@
|
||||
setDefaultTab("Tools")
|
||||
local panelName = "renameContainers"
|
||||
if type(storage[panelName]) ~= "table" then
|
||||
storage[panelName] = {
|
||||
enabled = false;
|
||||
height = 170,
|
||||
purse = true;
|
||||
list = {
|
||||
{
|
||||
value = "Main Backpack",
|
||||
enabled = true,
|
||||
item = 9601,
|
||||
min = false,
|
||||
items = { 3081, 3048 }
|
||||
},
|
||||
{
|
||||
value = "Runes",
|
||||
enabled = true,
|
||||
item = 2866,
|
||||
min = true,
|
||||
items = { 3161, 3180 }
|
||||
},
|
||||
{
|
||||
value = "Money",
|
||||
enabled = true,
|
||||
item = 2871,
|
||||
min = true,
|
||||
items = { 3031, 3035, 3043 }
|
||||
},
|
||||
{
|
||||
value = "Purse",
|
||||
enabled = true,
|
||||
item = 23396,
|
||||
min = true,
|
||||
items = {}
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
UI.Separator()
|
||||
local renameContui = setupUI([[
|
||||
Panel
|
||||
height: 50
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: Container Panel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Open Minimised')
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: editContList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: reopenCont
|
||||
!text: tr('Reopen All')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
height: 17
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: minimiseCont
|
||||
!text: tr('Minimise All')
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
height: 17
|
||||
font: verdana-11px-rounded
|
||||
]])
|
||||
renameContui:setId(panelName)
|
||||
|
||||
g_ui.loadUIFromString([[
|
||||
BackpackName < Label
|
||||
background-color: alpha
|
||||
text-offset: 18 2
|
||||
focusable: true
|
||||
height: 17
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 1
|
||||
margin-left: 3
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: state
|
||||
!text: tr('M')
|
||||
anchors.right: remove.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-right: 1
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!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: 465 170
|
||||
@onEscape: self:hide()
|
||||
|
||||
TextList
|
||||
id: itemList
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: separator.top
|
||||
width: 200
|
||||
margin-bottom: 6
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
vertical-scrollbar: itemListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemListScrollBar
|
||||
anchors.top: itemList.top
|
||||
anchors.bottom: itemList.bottom
|
||||
anchors.right: itemList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
VerticalSeparator
|
||||
id: sep
|
||||
anchors.top: parent.top
|
||||
anchors.left: itemList.right
|
||||
anchors.bottom: separator.top
|
||||
margin-top: 3
|
||||
margin-bottom: 6
|
||||
margin-left: 10
|
||||
|
||||
Label
|
||||
id: lblName
|
||||
anchors.left: sep.right
|
||||
anchors.top: sep.top
|
||||
width: 70
|
||||
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
|
||||
anchors.left: lblName.left
|
||||
anchors.verticalCenter: contId.verticalCenter
|
||||
width: 70
|
||||
text: Container:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotItem
|
||||
id: contId
|
||||
anchors.left: contName.left
|
||||
anchors.top: contName.bottom
|
||||
margin-top: 3
|
||||
|
||||
BotContainer
|
||||
id: sortList
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: separator.top
|
||||
margin-bottom: 6
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
anchors.left: lblCont.left
|
||||
anchors.verticalCenter: sortList.verticalCenter
|
||||
width: 70
|
||||
text: Items:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.right: contName.right
|
||||
anchors.top: contName.bottom
|
||||
margin-top: 5
|
||||
text: Add
|
||||
width: 40
|
||||
font: cipsoftFont
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
CheckBox
|
||||
id: purse
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
text: Open Purse
|
||||
tooltip: Opens Store/Charm Purse
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: sort
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Sort Items
|
||||
tooltip: Sort items based on items widget
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: forceOpen
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Keep Open
|
||||
tooltip: Will keep open containers all the time
|
||||
width: 85
|
||||
height: 15
|
||||
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
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
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)
|
||||
local tArray = {}
|
||||
for x,v in pairs(t) do
|
||||
if type(v) == "table" then
|
||||
local aItem = t[x].item
|
||||
local aEnabled = t[x].enabled
|
||||
if aItem then
|
||||
if tfind and aItem == tfind then
|
||||
return x
|
||||
elseif not tfind then
|
||||
if aEnabled then
|
||||
table.insert(tArray, aItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not tfind then return tArray end
|
||||
end
|
||||
|
||||
local lstBPs
|
||||
|
||||
|
||||
local openContainer = function(id)
|
||||
local t = {getRight(), getLeft(), getAmmo()} -- if more slots needed then add them here
|
||||
for i=1,#t do
|
||||
local slotItem = t[i]
|
||||
if slotItem and slotItem:getId() == id then
|
||||
return g_game.open(slotItem, nil)
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(g_game.getContainers()) do
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and item:getId() == id then
|
||||
return g_game.open(item, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function reopenBackpacks()
|
||||
lstBPs = findItemsInArray(config.list)
|
||||
|
||||
for _, container in pairs(g_game.getContainers()) do g_game.close(container) end
|
||||
bpItem = getBack()
|
||||
if bpItem ~= nil then
|
||||
g_game.open(bpItem)
|
||||
end
|
||||
|
||||
schedule(500, function()
|
||||
local delay = 200
|
||||
|
||||
if config.purse then
|
||||
local item = getPurse()
|
||||
if item then
|
||||
use(item)
|
||||
end
|
||||
end
|
||||
for i=1,#lstBPs do
|
||||
schedule(delay, function()
|
||||
openContainer(lstBPs[i])
|
||||
end)
|
||||
delay = delay + 250
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
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()
|
||||
contListWindow:focus()
|
||||
end
|
||||
|
||||
renameContui.reopenCont.onClick = function(widget)
|
||||
reopenBackpacks()
|
||||
end
|
||||
|
||||
renameContui.minimiseCont.onClick = function(widget)
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local containerWindow = container.window
|
||||
containerWindow:setContentHeight(34)
|
||||
end
|
||||
end
|
||||
|
||||
renameContui.title:setOn(config.enabled)
|
||||
renameContui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
contListWindow.closeButton.onClick = function(widget)
|
||||
contListWindow:hide()
|
||||
end
|
||||
|
||||
contListWindow.purse.onClick = function(widget)
|
||||
config.purse = not config.purse
|
||||
contListWindow.purse:setChecked(config.purse)
|
||||
end
|
||||
contListWindow.purse:setChecked(config.purse)
|
||||
|
||||
contListWindow.sort.onClick = function(widget)
|
||||
config.sort = not config.sort
|
||||
contListWindow.sort:setChecked(config.sort)
|
||||
end
|
||||
contListWindow.sort:setChecked(config.sort)
|
||||
|
||||
contListWindow.forceOpen.onClick = function(widget)
|
||||
config.forceOpen = not config.forceOpen
|
||||
contListWindow.forceOpen:setChecked(config.forceOpen)
|
||||
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()
|
||||
t = contListWindow.sortList:getItems()
|
||||
config.list[k].items = t
|
||||
end, true, nil, contListWindow.sortList)
|
||||
contListWindow.sortList:setItems(t)
|
||||
end
|
||||
refreshSortList(t)
|
||||
|
||||
local refreshContNames = function(tFocus)
|
||||
local storageVal = config.list
|
||||
if storageVal and #storageVal > 0 then
|
||||
for i, child in pairs(contListWindow.itemList:getChildren()) do
|
||||
child:destroy()
|
||||
end
|
||||
for k, entry in pairs(storageVal) do
|
||||
local label = g_ui.createWidget("BackpackName", contListWindow.itemList)
|
||||
label.onMouseRelease = function()
|
||||
contListWindow.contId:setItemId(entry.item)
|
||||
contListWindow.contName:setText(entry.value)
|
||||
if not entry.items then
|
||||
entry.items = {}
|
||||
end
|
||||
contListWindow.sortList:setItems(entry.items)
|
||||
refreshSortList(k, entry.items)
|
||||
end
|
||||
label.enabled.onClick = function(widget)
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled:setTooltip(entry.enabled and 'Disable' or 'Enable')
|
||||
label.enabled:setImageColor(entry.enabled and '#00FF00' or '#FF0000')
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(config.list, entry)
|
||||
label:destroy()
|
||||
end
|
||||
label.state:setChecked(entry.min)
|
||||
label.state.onClick = function(widget)
|
||||
entry.min = not entry.min
|
||||
label.state:setChecked(entry.min)
|
||||
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
|
||||
end
|
||||
end
|
||||
if tFocus then contListWindow.itemList:focusChild(tFocus) end
|
||||
end
|
||||
end
|
||||
contListWindow.addItem.onClick = function(widget)
|
||||
local id = contListWindow.contId:getItemId()
|
||||
local trigger = contListWindow.contName:getText()
|
||||
|
||||
if id > 100 and trigger:len() > 0 then
|
||||
local ifind = findItemsInArray(config.list, id)
|
||||
if ifind then
|
||||
config.list[ifind] = { item = id, value = trigger, enabled = config.list[ifind].enabled, min = config.list[ifind].min, items = config.list[ifind].items}
|
||||
else
|
||||
table.insert(config.list, { item = id, value = trigger, enabled = true, min = false, items = {} })
|
||||
end
|
||||
contListWindow.contId:setItemId(0)
|
||||
contListWindow.contName:setText('')
|
||||
contListWindow.contName:setColor('white')
|
||||
contListWindow.contName:setImageColor('#ffffff')
|
||||
contListWindow.contId:setImageColor('#ffffff')
|
||||
refreshContNames(id)
|
||||
else
|
||||
contListWindow.contId:setImageColor('red')
|
||||
contListWindow.contName:setImageColor('red')
|
||||
contListWindow.contName:setColor('red')
|
||||
end
|
||||
end
|
||||
refreshContNames()
|
||||
end
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
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
|
||||
if entry.enabled and string.find(container:getContainerItem():getId(), entry.item) then
|
||||
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
|
||||
|
||||
local function properTable(t)
|
||||
local r = {}
|
||||
for _, entry in pairs(t) do
|
||||
if type(entry) == "number" then
|
||||
table.insert(r, entry)
|
||||
else
|
||||
table.insert(r, entry.id)
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local mainLoop = macro(150, function(macro)
|
||||
if not config.sort and not config.purse then return end
|
||||
|
||||
local storageVal = config.list
|
||||
for _, entry in pairs(storageVal) do
|
||||
local dId = entry.item
|
||||
local items = properTable(entry.items)
|
||||
-- sorting
|
||||
if config.sort then
|
||||
for _, container in pairs(getContainers()) do
|
||||
local cName = container:getName():lower()
|
||||
if not cName:find("depot") and not cName:find("depot") and not cName:find("quiver") then
|
||||
local cId = container:getContainerItem():getId()
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(items, id) and cId ~= dId then
|
||||
local destination = getContainerByItem(dId, true)
|
||||
if destination and not containerIsFull(destination) then
|
||||
return moveItem(item, destination)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- keep open / purse 23396
|
||||
if config.forceOpen then
|
||||
local container = getContainerByItem(dId)
|
||||
if not container then
|
||||
local t = {getBack(), getAmmo(), getFinger(), getNeck(), getLeft(), getRight()}
|
||||
for i=1,#t do
|
||||
local slot = t[i]
|
||||
if slot and slot:getId() == dId then
|
||||
return g_game.open(slot)
|
||||
end
|
||||
end
|
||||
local cItem = findItem(dId)
|
||||
if cItem then
|
||||
return g_game.open(cItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
macro:setOff()
|
||||
end)
|
||||
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onPlayerInventoryChange(function(slot, item, oldItem)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onContainerClose(function(container)
|
||||
if not container.lootContainer then
|
||||
mainLoop:setOn()
|
||||
end
|
||||
end)
|
146
modules/game_bot/default_configs/vBot_4.8/vBot/Dropper.lua
Normal file
@ -0,0 +1,146 @@
|
||||
setDefaultTab("Tools")
|
||||
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Dropper')
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Edit
|
||||
]])
|
||||
|
||||
local edit = setupUI([[
|
||||
Panel
|
||||
height: 150
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
text-align: center
|
||||
text: Trash:
|
||||
|
||||
BotContainer
|
||||
id: TrashItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
|
||||
Label
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Use:
|
||||
|
||||
BotContainer
|
||||
id: UseItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
|
||||
Label
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Drop if below 150 cap:
|
||||
|
||||
BotContainer
|
||||
id: CapItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
]])
|
||||
edit:hide()
|
||||
|
||||
if not storage.dropper then
|
||||
storage.dropper = {
|
||||
enabled = false,
|
||||
trashItems = { 283, 284, 285 },
|
||||
useItems = { 21203, 14758 },
|
||||
capItems = { 21175 }
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage.dropper
|
||||
|
||||
local showEdit = false
|
||||
ui.edit.onClick = function(widget)
|
||||
showEdit = not showEdit
|
||||
if showEdit then
|
||||
edit:show()
|
||||
else
|
||||
edit:hide()
|
||||
end
|
||||
end
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
ui.title:setOn(config.enabled)
|
||||
end
|
||||
|
||||
UI.Container(function()
|
||||
config.trashItems = edit.TrashItems:getItems()
|
||||
end, true, nil, edit.TrashItems)
|
||||
edit.TrashItems:setItems(config.trashItems)
|
||||
|
||||
UI.Container(function()
|
||||
config.useItems = edit.UseItems:getItems()
|
||||
end, true, nil, edit.UseItems)
|
||||
edit.UseItems:setItems(config.useItems)
|
||||
|
||||
UI.Container(function()
|
||||
config.capItems = edit.CapItems:getItems()
|
||||
end, true, nil, edit.CapItems)
|
||||
edit.CapItems:setItems(config.capItems)
|
||||
|
||||
local function properTable(t)
|
||||
local r = {}
|
||||
|
||||
for _, entry in pairs(t) do
|
||||
table.insert(r, entry.id)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
macro(200, function()
|
||||
if not config.enabled then return end
|
||||
local tables = {properTable(config.capItems), properTable(config.useItems), properTable(config.trashItems)}
|
||||
|
||||
local containers = getContainers()
|
||||
for i=1,3 do
|
||||
for _, container in pairs(containers) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
for ___, userItem in ipairs(tables[i]) do
|
||||
if item:getId() == userItem then
|
||||
return i == 1 and freecap() < 150 and dropItem(item) or
|
||||
i == 2 and use(item) or
|
||||
i == 3 and dropItem(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
775
modules/game_bot/default_configs/vBot_4.8/vBot/Equipper.lua
Normal file
@ -0,0 +1,775 @@
|
||||
local panelName = "EquipperPanel"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: switch
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('EQ Manager')
|
||||
|
||||
Button
|
||||
id: setup
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] or not storage[panelName].bosses then -- no bosses - old ver
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
rules = {},
|
||||
bosses = {}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.switch:setOn(config.enabled)
|
||||
ui.switch.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
local conditions = { -- always add new conditions at the bottom
|
||||
"Item is available and not worn.", -- nothing 1
|
||||
"Monsters around is more than: ", -- spinbox 2
|
||||
"Monsters around is less than: ", -- spinbox 3
|
||||
"Health precent is below:", -- spinbox 4
|
||||
"Health precent is above:", -- spinbox 5
|
||||
"Mana precent is below:", -- spinbox 6
|
||||
"Mana precent is above:", -- spinbox 7
|
||||
"Target name is:", -- BotTextEdit 8
|
||||
"Hotkey is being pressed:", -- BotTextEdit 9
|
||||
"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
|
||||
"TargetBot Danger is Above:", -- spinbox 14
|
||||
"Blacklist player in range (sqm)", -- spinbox 15
|
||||
"Target is Boss", -- nothing 16
|
||||
"Player is NOT in protection zone", -- nothing 17
|
||||
"CaveBot is ON, TargetBot is OFF" -- nothing 18
|
||||
}
|
||||
|
||||
local conditionNumber = 1
|
||||
local optionalConditionNumber = 2
|
||||
|
||||
local mainWindow = UI.createWindow("EquipWindow")
|
||||
mainWindow:hide()
|
||||
|
||||
ui.setup.onClick = function()
|
||||
mainWindow:show()
|
||||
mainWindow:raise()
|
||||
mainWindow:focus()
|
||||
end
|
||||
|
||||
local inputPanel = mainWindow.inputPanel
|
||||
local listPanel = mainWindow.listPanel
|
||||
local namePanel = mainWindow.profileName
|
||||
local eqPanel = mainWindow.setup
|
||||
local bossPanel = mainWindow.bossPanel
|
||||
|
||||
local slotWidgets = {eqPanel.head, eqPanel.body, eqPanel.legs, eqPanel.feet, eqPanel.neck, eqPanel["left-hand"], eqPanel["right-hand"], eqPanel.finger, eqPanel.ammo} -- back is disabled
|
||||
|
||||
local function setCondition(first, n)
|
||||
local widget
|
||||
local spinBox
|
||||
local textEdit
|
||||
|
||||
if first then
|
||||
widget = inputPanel.condition.description.text
|
||||
spinBox = inputPanel.condition.spinbox
|
||||
textEdit = inputPanel.condition.text
|
||||
else
|
||||
widget = inputPanel.optionalCondition.description.text
|
||||
spinBox = inputPanel.optionalCondition.spinbox
|
||||
textEdit = inputPanel.optionalCondition.text
|
||||
end
|
||||
|
||||
-- reset values after change
|
||||
spinBox:setValue(0)
|
||||
textEdit:setText('')
|
||||
|
||||
if n == 1 or n == 10 or n == 11 or n == 16 or n == 17 or n == 18 then
|
||||
spinBox:hide()
|
||||
textEdit:hide()
|
||||
elseif n == 9 or n == 8 then
|
||||
spinBox:hide()
|
||||
textEdit:show()
|
||||
if n == 9 then
|
||||
textEdit:setWidth(75)
|
||||
else
|
||||
textEdit:setWidth(200)
|
||||
end
|
||||
else
|
||||
spinBox:show()
|
||||
textEdit:hide()
|
||||
end
|
||||
widget:setText(conditions[n])
|
||||
end
|
||||
|
||||
local function resetFields()
|
||||
conditionNumber = 1
|
||||
optionalConditionNumber = 2
|
||||
setCondition(false, optionalConditionNumber)
|
||||
setCondition(true, conditionNumber)
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
widget:setItemId(0)
|
||||
widget:setChecked(false)
|
||||
end
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
child.display = false
|
||||
end
|
||||
namePanel.profileName:setText("")
|
||||
inputPanel.condition.text:setText('')
|
||||
inputPanel.condition.spinbox:setValue(0)
|
||||
inputPanel.useSecondCondition:setText('-')
|
||||
inputPanel.optionalCondition.text:setText('')
|
||||
inputPanel.optionalCondition.spinbox:setValue(0)
|
||||
inputPanel.optionalCondition:hide()
|
||||
bossPanel:hide()
|
||||
listPanel:show()
|
||||
mainWindow.bossList:setText('Boss List')
|
||||
bossPanel.name:setText('')
|
||||
end
|
||||
resetFields()
|
||||
|
||||
mainWindow.closeButton.onClick = function()
|
||||
resetFields()
|
||||
mainWindow:hide()
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition:hide()
|
||||
inputPanel.useSecondCondition.onOptionChange = function(widget, option, data)
|
||||
if option ~= "-" then
|
||||
inputPanel.optionalCondition:show()
|
||||
else
|
||||
inputPanel.optionalCondition:hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- add default text & windows
|
||||
setCondition(true, 1)
|
||||
setCondition(false, 2)
|
||||
|
||||
-- in/de/crementation buttons
|
||||
inputPanel.condition.nex.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if inputPanel.optionalCondition:isVisible() then
|
||||
if conditionNumber == max then
|
||||
if optionalConditionNumber == 1 then
|
||||
conditionNumber = 2
|
||||
else
|
||||
conditionNumber = 1
|
||||
end
|
||||
else
|
||||
local futureNumber = conditionNumber + 1
|
||||
local safeFutureNumber = conditionNumber + 2 > max and 1 or conditionNumber + 2
|
||||
conditionNumber = futureNumber ~= optionalConditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
else
|
||||
conditionNumber = conditionNumber == max and 1 or conditionNumber + 1
|
||||
if optionalConditionNumber == conditionNumber then
|
||||
optionalConditionNumber = optionalConditionNumber == max and 1 or optionalConditionNumber + 1
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
end
|
||||
setCondition(true, conditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.condition.pre.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if inputPanel.optionalCondition:isVisible() then
|
||||
if conditionNumber == 1 then
|
||||
if optionalConditionNumber == max then
|
||||
conditionNumber = max-1
|
||||
else
|
||||
conditionNumber = max
|
||||
end
|
||||
else
|
||||
local futureNumber = conditionNumber - 1
|
||||
local safeFutureNumber = conditionNumber - 2 < 1 and max or conditionNumber - 2
|
||||
conditionNumber = futureNumber ~= optionalConditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
else
|
||||
conditionNumber = conditionNumber == 1 and max or conditionNumber - 1
|
||||
if optionalConditionNumber == conditionNumber then
|
||||
optionalConditionNumber = optionalConditionNumber == 1 and max or optionalConditionNumber - 1
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
end
|
||||
setCondition(true, conditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.nex.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if optionalConditionNumber == max then
|
||||
if conditionNumber == 1 then
|
||||
optionalConditionNumber = 2
|
||||
else
|
||||
optionalConditionNumber = 1
|
||||
end
|
||||
else
|
||||
local futureNumber = optionalConditionNumber + 1
|
||||
local safeFutureNumber = optionalConditionNumber + 2 > max and 1 or optionalConditionNumber + 2
|
||||
optionalConditionNumber = futureNumber ~= conditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.pre.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if optionalConditionNumber == 1 then
|
||||
if conditionNumber == max then
|
||||
optionalConditionNumber = max-1
|
||||
else
|
||||
optionalConditionNumber = max
|
||||
end
|
||||
else
|
||||
local futureNumber = optionalConditionNumber - 1
|
||||
local safeFutureNumber = optionalConditionNumber - 2 < 1 and max or optionalConditionNumber - 2
|
||||
optionalConditionNumber = futureNumber ~= conditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
|
||||
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]
|
||||
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(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]
|
||||
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
|
||||
|
||||
eqPanel.cloneEq.onClick = function(widget)
|
||||
eqPanel.head:setItemId(getHead() and getHead():getId() or 0)
|
||||
eqPanel.body:setItemId(getBody() and getBody():getId() or 0)
|
||||
eqPanel.legs:setItemId(getLeg() and getLeg():getId() or 0)
|
||||
eqPanel.feet:setItemId(getFeet() and getFeet():getId() or 0)
|
||||
eqPanel.neck:setItemId(getNeck() and getNeck():getId() or 0)
|
||||
eqPanel["left-hand"]:setItemId(getLeft() and getLeft():getId() or 0)
|
||||
eqPanel["right-hand"]:setItemId(getRight() and getRight():getId() or 0)
|
||||
eqPanel.finger:setItemId(getFinger() and getFinger():getId() or 0)
|
||||
eqPanel.ammo:setItemId(getAmmo() and getAmmo():getId() or 0)
|
||||
end
|
||||
|
||||
eqPanel.default.onClick = resetFields
|
||||
|
||||
-- buttons disabled by default
|
||||
listPanel.up:setEnabled(false)
|
||||
listPanel.down:setEnabled(false)
|
||||
|
||||
-- correct background image
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
widget:setTooltip("Right click to set as slot to unequip")
|
||||
widget.onItemChange = function(widget)
|
||||
local selfId = widget:getItemId()
|
||||
widget:setOn(selfId > 100)
|
||||
if widget:isChecked() then
|
||||
widget:setChecked(selfId < 100)
|
||||
end
|
||||
end
|
||||
widget.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local clearItem = widget:isChecked() == false
|
||||
widget:setChecked(not widget:isChecked())
|
||||
if clearItem then
|
||||
widget:setItemId(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
inputPanel.condition.description.onMouseWheel = function(widget, mousePos, scroll)
|
||||
if scroll == 1 then
|
||||
inputPanel.condition.nex.onClick()
|
||||
else
|
||||
inputPanel.condition.pre.onClick()
|
||||
end
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.description.onMouseWheel = function(widget, mousePos, scroll)
|
||||
if scroll == 1 then
|
||||
inputPanel.optionalCondition.nex.onClick()
|
||||
else
|
||||
inputPanel.optionalCondition.pre.onClick()
|
||||
end
|
||||
end
|
||||
|
||||
namePanel.profileName.onTextChange = function(widget, text)
|
||||
local button = inputPanel.add
|
||||
text = text:lower()
|
||||
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
local name = child:getText():lower()
|
||||
|
||||
button:setText(name == text and "Overwrite" or "Add Rule")
|
||||
button:setTooltip(name == text and "Overwrite existing rule named: "..name, "Add new rule to the list: "..name)
|
||||
end
|
||||
end
|
||||
|
||||
local function setupPreview(display, data)
|
||||
namePanel.profileName:setText('')
|
||||
if not display then
|
||||
resetFields()
|
||||
else
|
||||
for i, value in ipairs(data) do
|
||||
local widget = slotWidgets[i]
|
||||
if value == false then
|
||||
widget:setChecked(false)
|
||||
widget:setItemId(0)
|
||||
elseif value == true then
|
||||
widget:setChecked(true)
|
||||
widget:setItemId(0)
|
||||
else
|
||||
widget:setChecked(false)
|
||||
widget:setItemId(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshRules()
|
||||
local list = listPanel.list
|
||||
|
||||
list:destroyChildren()
|
||||
for i,v in ipairs(config.rules) do
|
||||
local widget = UI.createWidget('Rule', list)
|
||||
widget:setId(v.name)
|
||||
widget:setText(v.name)
|
||||
widget.ruleData = v
|
||||
widget.remove.onClick = function()
|
||||
widget:destroy()
|
||||
table.remove(config.rules, table.find(config.rules, v))
|
||||
listPanel.up:setEnabled(false)
|
||||
listPanel.down:setEnabled(false)
|
||||
refreshRules()
|
||||
end
|
||||
widget.visible:setColor(v.visible and "green" or "red")
|
||||
widget.visible.onClick = function()
|
||||
v.visible = not v.visible
|
||||
widget.visible:setColor(v.visible and "green" or "red")
|
||||
end
|
||||
widget.enabled:setChecked(v.enabled)
|
||||
widget.enabled.onClick = function()
|
||||
v.enabled = not v.enabled
|
||||
widget.enabled:setChecked(v.enabled)
|
||||
end
|
||||
widget.onHoverChange = function(widget, hover)
|
||||
for i, child in ipairs(list:getChildren()) do
|
||||
if child.display then return end
|
||||
end
|
||||
setupPreview(hover, widget.ruleData.data)
|
||||
end
|
||||
widget.onDoubleClick = function(widget)
|
||||
local ruleData = widget.ruleData
|
||||
widget.display = true
|
||||
setupPreview(true, ruleData.data)
|
||||
conditionNumber = ruleData.mainCondition
|
||||
optionalConditionNumber = ruleData.optionalCondition
|
||||
setCondition(false, optionalConditionNumber)
|
||||
setCondition(true, conditionNumber)
|
||||
inputPanel.useSecondCondition:setOption(ruleData.relation)
|
||||
namePanel.profileName:setText(v.name)
|
||||
|
||||
if type(ruleData.mainValue) == "string" then
|
||||
inputPanel.condition.text:setText(ruleData.mainValue)
|
||||
elseif type(ruleData.mainValue) == "number" then
|
||||
inputPanel.condition.spinbox:setValue(ruleData.mainValue)
|
||||
end
|
||||
|
||||
if type(ruleData.optValue) == "string" then
|
||||
inputPanel.optionalCondition.text:setText(ruleData.optValue)
|
||||
elseif type(ruleData.optValue) == "number" then
|
||||
inputPanel.optionalCondition.spinbox:setValue(ruleData.optValue)
|
||||
end
|
||||
end
|
||||
widget.onClick = function()
|
||||
local panel = listPanel
|
||||
if #panel.list:getChildren() == 1 then
|
||||
panel.up:setEnabled(false)
|
||||
panel.down:setEnabled(false)
|
||||
elseif panel.list:getChildIndex(panel.list:getFocusedChild()) == 1 then
|
||||
panel.up:setEnabled(false)
|
||||
panel.down:setEnabled(true)
|
||||
elseif panel.list:getChildIndex(panel.list:getFocusedChild()) == #panel.list:getChildren() then
|
||||
panel.up:setEnabled(true)
|
||||
panel.down:setEnabled(false)
|
||||
else
|
||||
panel.up:setEnabled(true)
|
||||
panel.down:setEnabled(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshRules()
|
||||
|
||||
inputPanel.add.onClick = function(widget)
|
||||
local mainVal
|
||||
local optVal
|
||||
local t = {}
|
||||
local relation = inputPanel.useSecondCondition:getText()
|
||||
local profileName = namePanel.profileName:getText()
|
||||
if profileName:len() == 0 then
|
||||
return warn("Please fill profile name!")
|
||||
end
|
||||
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
local checked = widget:isChecked()
|
||||
local id = widget:getItemId()
|
||||
|
||||
if checked then
|
||||
table.insert(t, true) -- unequip selected slot
|
||||
elseif id then
|
||||
table.insert(t, id) -- equip selected item
|
||||
else
|
||||
table.insert(t, false) -- ignore slot
|
||||
end
|
||||
end
|
||||
|
||||
if conditionNumber == 1 then
|
||||
mainVal = nil
|
||||
elseif conditionNumber == 8 then
|
||||
mainVal = inputPanel.condition.text:getText()
|
||||
if mainVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please fill the name of the creature.")
|
||||
end
|
||||
elseif conditionNumber == 9 then
|
||||
mainVal = inputPanel.condition.text:getText()
|
||||
if mainVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please set correct hotkey.")
|
||||
end
|
||||
else
|
||||
mainVal = inputPanel.condition.spinbox:getValue()
|
||||
end
|
||||
|
||||
if relation ~= "-" then
|
||||
if optionalConditionNumber == 1 then
|
||||
optVal = nil
|
||||
elseif optionalConditionNumber == 8 then
|
||||
optVal = inputPanel.optionalCondition.text:getText()
|
||||
if optVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please fill the name of the creature.")
|
||||
end
|
||||
elseif optionalConditionNumber == 9 then
|
||||
optVal = inputPanel.optionalCondition.text:getText()
|
||||
if optVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please set correct hotkey.")
|
||||
end
|
||||
else
|
||||
optVal = inputPanel.optionalCondition.spinbox:getValue()
|
||||
end
|
||||
end
|
||||
|
||||
local index
|
||||
for i, v in ipairs(config.rules) do
|
||||
if v.name == profileName then
|
||||
index = i -- search if there's already rule with this name
|
||||
end
|
||||
end
|
||||
|
||||
local ruleData = {
|
||||
name = profileName,
|
||||
data = t,
|
||||
enabled = true,
|
||||
visible = true,
|
||||
mainCondition = conditionNumber,
|
||||
optionalCondition = optionalConditionNumber,
|
||||
mainValue = mainVal,
|
||||
optValue = optVal,
|
||||
relation = relation,
|
||||
}
|
||||
|
||||
if index then
|
||||
config.rules[index] = ruleData -- overwrite
|
||||
else
|
||||
table.insert(config.rules, ruleData) -- create new one
|
||||
end
|
||||
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
child.display = false
|
||||
end
|
||||
resetFields()
|
||||
refreshRules()
|
||||
end
|
||||
|
||||
mainWindow.bossList.onClick = function(widget)
|
||||
if bossPanel:isVisible() then
|
||||
bossPanel:hide()
|
||||
listPanel:show()
|
||||
widget:setText('Boss List')
|
||||
else
|
||||
bossPanel:show()
|
||||
listPanel:hide()
|
||||
widget:setText('Rule List')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- create boss labels
|
||||
for i, v in ipairs(config.bosses) do
|
||||
local widget = UI.createWidget("BossLabel", bossPanel.list)
|
||||
widget:setText(v)
|
||||
widget.remove.onClick = function()
|
||||
table.remove(config.bosses, table.find(config.bosses, v))
|
||||
widget:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
bossPanel.add.onClick = function()
|
||||
local name = bossPanel.name:getText()
|
||||
|
||||
if name:len() == 0 then
|
||||
return warn("[Equipped] Please enter boss name!")
|
||||
elseif table.find(config.bosses, name:lower(), true) then
|
||||
return warn("[Equipper] Boss already added!")
|
||||
end
|
||||
|
||||
local widget = UI.createWidget("BossLabel", bossPanel.list)
|
||||
widget:setText(name)
|
||||
widget.remove.onClick = function()
|
||||
table.remove(config.bosses, table.find(config.bosses, name))
|
||||
widget:destroy()
|
||||
end
|
||||
|
||||
table.insert(config.bosses, name)
|
||||
bossPanel.name:setText('')
|
||||
end
|
||||
|
||||
local function interpreteCondition(n, v)
|
||||
|
||||
if n == 1 then
|
||||
return true
|
||||
elseif n == 2 then
|
||||
return getMonsters() > v
|
||||
elseif n == 3 then
|
||||
return getMonsters() < v
|
||||
elseif n == 4 then
|
||||
return hppercent() < v
|
||||
elseif n == 5 then
|
||||
return hppercent() > v
|
||||
elseif n == 6 then
|
||||
return manapercent() < v
|
||||
elseif n == 7 then
|
||||
return manapercent() > v
|
||||
elseif n == 8 then
|
||||
return target() and target():getName():lower() == v:lower() or false
|
||||
elseif n == 9 then
|
||||
return g_keyboard.isKeyPressed(v)
|
||||
elseif n == 10 then
|
||||
return isParalyzed()
|
||||
elseif n == 11 then
|
||||
return isInPz()
|
||||
elseif n == 12 then
|
||||
return getPlayers() > v
|
||||
elseif n == 13 then
|
||||
return getPlayers() < v
|
||||
elseif n == 14 then
|
||||
return TargetBot.Danger() > v and TargetBot.isOn()
|
||||
elseif n == 15 then
|
||||
return isBlackListedPlayerInRange(v)
|
||||
elseif n == 16 then
|
||||
return target() and table.find(config.bosses, target():getName():lower(), true) and true or false
|
||||
elseif n == 17 then
|
||||
return not isInPz()
|
||||
elseif n == 18 then
|
||||
return CaveBot.isOn() and TargetBot.isOff()
|
||||
end
|
||||
end
|
||||
|
||||
local function finalCheck(first,relation,second)
|
||||
if relation == "-" then
|
||||
return first
|
||||
elseif relation == "and" then
|
||||
return first and second
|
||||
elseif relation == "or" then
|
||||
return first or second
|
||||
end
|
||||
end
|
||||
|
||||
local function isEquipped(id)
|
||||
local t = {getNeck(), getHead(), getBody(), getRight(), getLeft(), getLeg(), getFeet(), getFinger(), getAmmo()}
|
||||
local ids = {id, getInactiveItemId(id), getActiveItemId(id)}
|
||||
|
||||
for i, slot in pairs(t) do
|
||||
if slot and table.find(ids, slot:getId()) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function unequipItem(table)
|
||||
local slots = {getHead(), getBody(), getLeg(), getFeet(), getNeck(), getLeft(), getRight(), getFinger(), getAmmo()}
|
||||
|
||||
if type(table) ~= "table" then return end
|
||||
for i, slot in ipairs(table) do
|
||||
local physicalSlot = slots[i]
|
||||
|
||||
if slot == true and physicalSlot then
|
||||
local id = physicalSlot:getId()
|
||||
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
-- new tibia
|
||||
g_game.equipItemId(id)
|
||||
else
|
||||
-- old tibia
|
||||
local dest
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local cname = container:getName()
|
||||
if not containerIsFull(container) then
|
||||
if not cname:find("loot") and (cname:find("backpack") or cname:find("bag") or cname:find("chess")) then
|
||||
dest = container
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not dest then return true end
|
||||
local pos = dest:getSlotPosition(dest:getItemsCount())
|
||||
g_game.move(physicalSlot, pos, physicalSlot:getCount())
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function equipItem(id, slot)
|
||||
-- need to correct slots...
|
||||
if slot == 2 then
|
||||
slot = 4
|
||||
elseif slot == 3 then
|
||||
slot = 7
|
||||
elseif slot == 8 then
|
||||
slot = 9
|
||||
elseif slot == 5 then
|
||||
slot = 2
|
||||
elseif slot == 4 then
|
||||
slot = 8
|
||||
elseif slot == 9 then
|
||||
slot = 10
|
||||
elseif slot == 7 then
|
||||
slot = 5
|
||||
end
|
||||
|
||||
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
-- new tibia
|
||||
return g_game.equipItemId(id)
|
||||
else
|
||||
-- old tibia
|
||||
local item = findItem(id)
|
||||
return moveToSlot(item, slot)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function markChild(child)
|
||||
if mainWindow:isVisible() then
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
if child ~= widget then
|
||||
child:setColor('white')
|
||||
end
|
||||
end
|
||||
widget:setColor('green')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local missingItem = false
|
||||
local lastRule = false
|
||||
local correctEq = false
|
||||
EquipManager = macro(50, function()
|
||||
if not config.enabled then return end
|
||||
if #config.rules == 0 then return end
|
||||
|
||||
for i, widget in ipairs(listPanel.list:getChildren()) do
|
||||
local rule = widget.ruleData
|
||||
if rule.enabled then
|
||||
|
||||
-- conditions
|
||||
local firstCondition = interpreteCondition(rule.mainCondition, rule.mainValue)
|
||||
local optionalCondition = nil
|
||||
if rule.relation ~= "-" then
|
||||
optionalCondition = interpreteCondition(rule.optionalCondition, rule.optValue)
|
||||
end
|
||||
|
||||
-- checks
|
||||
if finalCheck(firstCondition, rule.relation, optionalCondition) then
|
||||
|
||||
-- performance edits, loop reset
|
||||
local resetLoop = not missingItem and correctEq and lastRule == rule
|
||||
if resetLoop then return end
|
||||
|
||||
-- reset executed rule
|
||||
|
||||
|
||||
-- first check unequip
|
||||
if unequipItem(rule.data) == true then
|
||||
delay(200)
|
||||
return
|
||||
end
|
||||
|
||||
-- equiploop
|
||||
for slot, item in ipairs(rule.data) do
|
||||
if type(item) == "number" and item > 100 then
|
||||
if not isEquipped(item) then
|
||||
if rule.visible then
|
||||
if findItem(item) then
|
||||
missingItem = false
|
||||
delay(200)
|
||||
return equipItem(item, slot)
|
||||
else
|
||||
missingItem = true
|
||||
end
|
||||
else
|
||||
missingItem = false
|
||||
delay(200)
|
||||
return equipItem(item, slot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
correctEq = not missingItem and true or false
|
||||
-- even if nothing was done, exit function to hold rule
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
712
modules/game_bot/default_configs/vBot_4.8/vBot/HealBot.lua
Normal file
@ -0,0 +1,712 @@
|
||||
local standBySpells = false
|
||||
local standByItems = false
|
||||
|
||||
local red = "#ff0800" -- "#ff0800" / #ea3c53 best
|
||||
local blue = "#7ef9ff"
|
||||
|
||||
setDefaultTab("HP")
|
||||
local healPanelName = "healbot"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 38
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('HealBot')
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
Button
|
||||
id: 1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text: 1
|
||||
margin-right: 2
|
||||
margin-top: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 2
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 2
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 3
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 3
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 4
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 5
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Label
|
||||
id: name
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-left: 4
|
||||
height: 17
|
||||
text: Profile #1
|
||||
background: #292A2A
|
||||
]])
|
||||
ui:setId(healPanelName)
|
||||
|
||||
if not HealBotConfig[healPanelName] or not HealBotConfig[healPanelName][1] or #HealBotConfig[healPanelName] ~= 5 then
|
||||
HealBotConfig[healPanelName] = {
|
||||
[1] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #1",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[2] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #2",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[3] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #3",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[4] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #4",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[5] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #5",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
if not HealBotConfig.currentHealBotProfile or HealBotConfig.currentHealBotProfile == 0 or HealBotConfig.currentHealBotProfile > 5 then
|
||||
HealBotConfig.currentHealBotProfile = 1
|
||||
end
|
||||
|
||||
-- finding correct table, manual unfortunately
|
||||
local currentSettings
|
||||
local setActiveProfile = function()
|
||||
local n = HealBotConfig.currentHealBotProfile
|
||||
currentSettings = HealBotConfig[healPanelName][n]
|
||||
end
|
||||
setActiveProfile()
|
||||
|
||||
local activeProfileColor = function()
|
||||
for i=1,5 do
|
||||
if i == HealBotConfig.currentHealBotProfile then
|
||||
ui[i]:setColor("green")
|
||||
else
|
||||
ui[i]:setColor("white")
|
||||
end
|
||||
end
|
||||
end
|
||||
activeProfileColor()
|
||||
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
currentSettings.enabled = not currentSettings.enabled
|
||||
widget:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
ui.settings.onClick = function(widget)
|
||||
healWindow:show()
|
||||
healWindow:raise()
|
||||
healWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
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.settings.profiles.Name.onTextChange = function(widget, text)
|
||||
currentSettings.name = text
|
||||
setProfileName()
|
||||
end
|
||||
healWindow.settings.list.Visible.onClick = function(widget)
|
||||
currentSettings.Visible = not currentSettings.Visible
|
||||
healWindow.settings.list.Visible:setChecked(currentSettings.Visible)
|
||||
end
|
||||
healWindow.settings.list.Cooldown.onClick = function(widget)
|
||||
currentSettings.Cooldown = not currentSettings.Cooldown
|
||||
healWindow.settings.list.Cooldown:setChecked(currentSettings.Cooldown)
|
||||
end
|
||||
healWindow.settings.list.Interval.onClick = function(widget)
|
||||
currentSettings.Interval = not currentSettings.Interval
|
||||
healWindow.settings.list.Interval:setChecked(currentSettings.Interval)
|
||||
end
|
||||
healWindow.settings.list.Conditions.onClick = function(widget)
|
||||
currentSettings.Conditions = not currentSettings.Conditions
|
||||
healWindow.settings.list.Conditions:setChecked(currentSettings.Conditions)
|
||||
end
|
||||
healWindow.settings.list.Delay.onClick = function(widget)
|
||||
currentSettings.Delay = not currentSettings.Delay
|
||||
healWindow.settings.list.Delay:setChecked(currentSettings.Delay)
|
||||
end
|
||||
healWindow.settings.list.MessageDelay.onClick = function(widget)
|
||||
currentSettings.MessageDelay = not currentSettings.MessageDelay
|
||||
healWindow.settings.list.MessageDelay:setChecked(currentSettings.MessageDelay)
|
||||
end
|
||||
|
||||
local refreshSpells = function()
|
||||
if currentSettings.spellTable then
|
||||
healWindow.healer.spells.spellList:destroyChildren()
|
||||
for _, entry in pairs(currentSettings.spellTable) do
|
||||
local label = UI.createWidget("SpellEntry", healWindow.healer.spells.spellList)
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
table.removevalue(currentSettings.spellTable, entry)
|
||||
reindexTable(currentSettings.spellTable)
|
||||
label:destroy()
|
||||
end
|
||||
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ": " .. entry.spell)
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshSpells()
|
||||
|
||||
local refreshItems = function()
|
||||
if currentSettings.itemTable then
|
||||
healWindow.healer.items.itemList:destroyChildren()
|
||||
for _, entry in pairs(currentSettings.itemTable) do
|
||||
local label = UI.createWidget("ItemEntry", healWindow.healer.items.itemList)
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
table.removevalue(currentSettings.itemTable, entry)
|
||||
reindexTable(currentSettings.itemTable)
|
||||
label:destroy()
|
||||
end
|
||||
label.id:setItemId(entry.item)
|
||||
label:setText(entry.origin .. entry.sign .. entry.value .. ": " .. entry.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshItems()
|
||||
|
||||
healWindow.healer.spells.MoveUp.onClick = function(widget)
|
||||
local input = healWindow.healer.spells.spellList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.spells.spellList:getChildIndex(input)
|
||||
if index < 2 then return end
|
||||
|
||||
local t = currentSettings.spellTable
|
||||
|
||||
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.healer.spells.MoveDown.onClick = function(widget)
|
||||
local input = healWindow.healer.spells.spellList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.spells.spellList:getChildIndex(input)
|
||||
if index >= healWindow.healer.spells.spellList:getChildCount() then return end
|
||||
|
||||
local t = currentSettings.spellTable
|
||||
|
||||
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.healer.items.MoveUp.onClick = function(widget)
|
||||
local input = healWindow.healer.items.itemList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.items.itemList:getChildIndex(input)
|
||||
if index < 2 then return end
|
||||
|
||||
local t = currentSettings.itemTable
|
||||
|
||||
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.healer.items.MoveDown.onClick = function(widget)
|
||||
local input = healWindow.healer.items.itemList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.items.itemList:getChildIndex(input)
|
||||
if index >= healWindow.healer.items.itemList:getChildCount() then return end
|
||||
|
||||
local t = currentSettings.itemTable
|
||||
|
||||
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.healer.spells.addSpell.onClick = function(widget)
|
||||
|
||||
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.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.healer.spells.spellFormula:setText('')
|
||||
healWindow.healer.spells.spellValue:setText('')
|
||||
healWindow.healer.spells.manaCost:setText('')
|
||||
return
|
||||
end
|
||||
|
||||
if spellSource == "Current Mana" then
|
||||
source = "MP"
|
||||
elseif spellSource == "Current Health" then
|
||||
source = "HP"
|
||||
elseif spellSource == "Mana Percent" then
|
||||
source = "MP%"
|
||||
elseif spellSource == "Health Percent" then
|
||||
source = "HP%"
|
||||
else
|
||||
source = "burst"
|
||||
end
|
||||
|
||||
if spellEquasion == "Above" then
|
||||
equasion = ">"
|
||||
elseif spellEquasion == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
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.healer.spells.spellFormula:setText('')
|
||||
healWindow.healer.spells.spellValue:setText('')
|
||||
healWindow.healer.spells.manaCost:setText('')
|
||||
end
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
refreshSpells()
|
||||
end
|
||||
|
||||
healWindow.healer.items.addItem.onClick = function(widget)
|
||||
|
||||
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.healer.items.itemId:setItemId(0)
|
||||
healWindow.healer.items.itemValue:setText('')
|
||||
return
|
||||
end
|
||||
|
||||
if src == "Current Mana" then
|
||||
source = "MP"
|
||||
elseif src == "Current Health" then
|
||||
source = "HP"
|
||||
elseif src == "Mana Percent" then
|
||||
source = "MP%"
|
||||
elseif src == "Health Percent" then
|
||||
source = "HP%"
|
||||
else
|
||||
source = "burst"
|
||||
end
|
||||
|
||||
if eq == "Above" then
|
||||
equasion = ">"
|
||||
elseif eq == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
if id > 100 then
|
||||
table.insert(currentSettings.itemTable, {index = #currentSettings.itemTable+1,item = id, sign = equasion, origin = source, value = trigger, enabled = true})
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
refreshItems()
|
||||
healWindow.healer.items.itemId:setItemId(0)
|
||||
healWindow.healer.items.itemValue:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.closeButton.onClick = function(widget)
|
||||
healWindow:hide()
|
||||
end
|
||||
|
||||
local loadSettings = function()
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
setProfileName()
|
||||
healWindow.settings.profiles.Name:setText(currentSettings.name)
|
||||
refreshSpells()
|
||||
refreshItems()
|
||||
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()
|
||||
|
||||
local profileChange = function()
|
||||
setActiveProfile()
|
||||
activeProfileColor()
|
||||
loadSettings()
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
local resetSettings = function()
|
||||
currentSettings.enabled = false
|
||||
currentSettings.spellTable = {}
|
||||
currentSettings.itemTable = {}
|
||||
currentSettings.Visible = true
|
||||
currentSettings.Cooldown = true
|
||||
currentSettings.Delay = true
|
||||
currentSettings.MessageDelay = false
|
||||
currentSettings.Interval = true
|
||||
currentSettings.Conditions = true
|
||||
currentSettings.name = "Profile #" .. HealBotConfig.currentBotProfile
|
||||
end
|
||||
|
||||
-- profile buttons
|
||||
for i=1,5 do
|
||||
local button = ui[i]
|
||||
button.onClick = function()
|
||||
HealBotConfig.currentHealBotProfile = i
|
||||
profileChange()
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.settings.profiles.ResetSettings.onClick = function()
|
||||
resetSettings()
|
||||
loadSettings()
|
||||
end
|
||||
|
||||
|
||||
-- public functions
|
||||
HealBot = {} -- global table
|
||||
|
||||
HealBot.isOn = function()
|
||||
return currentSettings.enabled
|
||||
end
|
||||
|
||||
HealBot.isOff = function()
|
||||
return not currentSettings.enabled
|
||||
end
|
||||
|
||||
HealBot.setOff = function()
|
||||
currentSettings.enabled = false
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("atk")
|
||||
end
|
||||
|
||||
HealBot.setOn = function()
|
||||
currentSettings.enabled = true
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("atk")
|
||||
end
|
||||
|
||||
HealBot.getActiveProfile = function()
|
||||
return HealBotConfig.currentHealBotProfile -- returns number 1-5
|
||||
end
|
||||
|
||||
HealBot.setActiveProfile = function(n)
|
||||
if not n or not tonumber(n) or n < 1 or n > 5 then
|
||||
return error("[HealBot] wrong profile parameter! should be 1 to 5 is " .. n)
|
||||
else
|
||||
HealBotConfig.currentHealBotProfile = n
|
||||
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 then return end
|
||||
local somethingIsOnCooldown = false
|
||||
|
||||
for _, entry in pairs(currentSettings.spellTable) do
|
||||
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)
|
||||
return
|
||||
elseif entry.sign == ">" and hppercent() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and hppercent() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "HP" then
|
||||
if entry.sign == "=" and hp() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and hp() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and hp() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP%" then
|
||||
if entry.sign == "=" and manapercent() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and manapercent() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and manapercent() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP" then
|
||||
if entry.sign == "=" and mana() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and mana() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and mana() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "burst" then
|
||||
if entry.sign == "=" and burstDamageValue() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and burstDamageValue() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and burstDamageValue() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
end
|
||||
else
|
||||
somethingIsOnCooldown = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not somethingIsOnCooldown then
|
||||
standBySpells = true
|
||||
end
|
||||
end)
|
||||
|
||||
-- items
|
||||
macro(100, function()
|
||||
if standByItems then return end
|
||||
if not currentSettings.enabled or #currentSettings.itemTable == 0 then return end
|
||||
if currentSettings.Delay and vBot.isUsing then return end
|
||||
if currentSettings.MessageDelay and vBot.isUsingPotion then return end
|
||||
|
||||
if not currentSettings.MessageDelay then
|
||||
delay(400)
|
||||
end
|
||||
|
||||
if TargetBot.isOn() and TargetBot.Looting.getStatus():len() > 0 and currentSettings.Interval then
|
||||
if not currentSettings.MessageDelay then
|
||||
delay(700)
|
||||
else
|
||||
delay(200)
|
||||
end
|
||||
end
|
||||
|
||||
for _, entry in pairs(currentSettings.itemTable) do
|
||||
local item = findItem(entry.item)
|
||||
if (not currentSettings.Visible or item) and entry.enabled then
|
||||
if entry.origin == "HP%" then
|
||||
if entry.sign == "=" and hppercent() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hppercent() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hppercent() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "HP" then
|
||||
if entry.sign == "=" and hp() == tonumberentry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hp() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hp() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP%" then
|
||||
if entry.sign == "=" and manapercent() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and manapercent() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and manapercent() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP" then
|
||||
if entry.sign == "=" and mana() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and mana() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and mana() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "burst" then
|
||||
if entry.sign == "=" and burstDamageValue() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and burstDamageValue() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and burstDamageValue() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
standByItems = true
|
||||
end)
|
||||
UI.Separator()
|
||||
|
||||
onPlayerHealthChange(function(healthPercent)
|
||||
standByItems = false
|
||||
standBySpells = false
|
||||
end)
|
||||
|
||||
onManaChange(function(player, mana, maxMana, oldMana, oldMaxMana)
|
||||
standByItems = false
|
||||
standBySpells = false
|
||||
end)
|
492
modules/game_bot/default_configs/vBot_4.8/vBot/HealBot.otui
Normal file
@ -0,0 +1,492 @@
|
||||
SettingCheckBox < CheckBox
|
||||
text-wrap: true
|
||||
text-auto-resize: true
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellSourceBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellSourceBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellSourceBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Current Mana")
|
||||
self:addOption("Current Health")
|
||||
self:addOption("Mana Percent")
|
||||
self:addOption("Health Percent")
|
||||
self:addOption("Burst Damage")
|
||||
|
||||
SpellConditionBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellConditionBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Below")
|
||||
self:addOption("Above")
|
||||
self:addOption("Equal To")
|
||||
|
||||
SpellEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 18 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
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!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: 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
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
text-offset: 1 0
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
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.verticalCenter: prev.verticalCenter
|
||||
text: When
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: isSpell
|
||||
anchors.left: spellList.right
|
||||
anchors.top: whenSpell.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellConditionBox
|
||||
id: spellCondition
|
||||
anchors.left: spellSource.left
|
||||
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
|
||||
anchors.right: spellSource.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: castSpell
|
||||
anchors.left: isSpell.left
|
||||
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
|
||||
anchors.left: castSpell.left
|
||||
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
|
||||
padding-top: 2
|
||||
width: 270
|
||||
margin-bottom: 7
|
||||
margin-left: 7
|
||||
margin-top: 10
|
||||
vertical-scrollbar: spellListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: spellListScrollBar
|
||||
anchors.top: spellList.top
|
||||
anchors.bottom: spellList.bottom
|
||||
anchors.right: spellList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: addSpell
|
||||
anchors.right: spellFormula.right
|
||||
anchors.bottom: spellList.bottom
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
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.verticalCenter: prev.verticalCenter
|
||||
text: When
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: isItem
|
||||
anchors.left: itemList.right
|
||||
anchors.top: whenItem.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellConditionBox
|
||||
id: itemCondition
|
||||
anchors.left: itemSource.left
|
||||
anchors.top: itemSource.bottom
|
||||
marin-top: 15
|
||||
width: 80
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: itemValue
|
||||
anchors.left: itemCondition.right
|
||||
anchors.top: itemCondition.top
|
||||
anchors.bottom: itemCondition.bottom
|
||||
width: 49
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: useItem
|
||||
anchors.left: isItem.left
|
||||
anchors.top: isItem.bottom
|
||||
text: Use
|
||||
margin-top: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.left: itemCondition.left
|
||||
anchors.top: itemCondition.bottom
|
||||
|
||||
TextList
|
||||
id: itemList
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
padding: 1
|
||||
padding-top: 2
|
||||
width: 270
|
||||
margin-top: 10
|
||||
margin-bottom: 7
|
||||
margin-left: 8
|
||||
vertical-scrollbar: itemListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemListScrollBar
|
||||
anchors.top: itemList.top
|
||||
anchors.bottom: itemList.bottom
|
||||
anchors.right: itemList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.right: itemValue.right
|
||||
anchors.bottom: itemList.bottom
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
HealerPanel < Panel
|
||||
size: 510 275
|
||||
|
||||
SpellHealing
|
||||
id: spells
|
||||
anchors.top: parent.top
|
||||
margin-top: 8
|
||||
anchors.left: parent.left
|
||||
|
||||
ItemHealing
|
||||
id: items
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
|
||||
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
|
||||
text: Additional Settings
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
SettingCheckBox
|
||||
id: Cooldown
|
||||
text: Check spell cooldowns
|
||||
margin-top: 10
|
||||
|
||||
SettingCheckBox
|
||||
id: Visible
|
||||
text: Items must be visible (recommended)
|
||||
|
||||
SettingCheckBox
|
||||
id: Delay
|
||||
text: Don't use items when interacting
|
||||
|
||||
SettingCheckBox
|
||||
id: Interval
|
||||
text: Additional delay when looting corpses
|
||||
|
||||
SettingCheckBox
|
||||
id: Conditions
|
||||
text: Also check conditions from RL Tibia
|
||||
|
||||
SettingCheckBox
|
||||
id: MessageDelay
|
||||
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
|
||||
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.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: ResetSettings
|
||||
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
|
||||
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
|
||||
|
||||
Button
|
||||
id: settingsButton
|
||||
!text: tr('Settings')
|
||||
font: cipsoftFont
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
252
modules/game_bot/default_configs/vBot_4.8/vBot/Sio.lua
Normal file
@ -0,0 +1,252 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "advancedFriendHealer"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Friend Healer')
|
||||
|
||||
Button
|
||||
id: editList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
minMana = 60,
|
||||
minFriendHp = 40,
|
||||
customSpellName = "exura max sio",
|
||||
customSpell = false,
|
||||
distance = 8,
|
||||
itemHeal = false,
|
||||
id = 3160,
|
||||
exuraSio = false,
|
||||
exuraGranSio = false,
|
||||
exuraMasRes = false,
|
||||
healEk = false,
|
||||
healRp = false,
|
||||
healEd = false,
|
||||
healMs = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
-- basic elements
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
ui.editList.onClick = function(widget)
|
||||
sioListWindow:show()
|
||||
sioListWindow:raise()
|
||||
sioListWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
sioListWindow = UI.createWindow('SioListWindow', rootWidget)
|
||||
sioListWindow:hide()
|
||||
|
||||
-- TextWindow
|
||||
sioListWindow.spellName:setText(config.customSpellName)
|
||||
sioListWindow.spellName.onTextChange = function(widget, text)
|
||||
config.customSpellName = text
|
||||
end
|
||||
|
||||
-- botswitches
|
||||
sioListWindow.spell:setOn(config.customSpell)
|
||||
sioListWindow.spell.onClick = function(widget)
|
||||
config.customSpell = not config.customSpell
|
||||
widget:setOn(config.customSpell)
|
||||
end
|
||||
sioListWindow.item:setOn(config.itemHeal)
|
||||
sioListWindow.item.onClick = function(widget)
|
||||
config.itemHeal = not config.itemHeal
|
||||
widget:setOn(config.itemHeal)
|
||||
end
|
||||
sioListWindow.exuraSio:setOn(config.exuraSio)
|
||||
sioListWindow.exuraSio.onClick = function(widget)
|
||||
config.exuraSio = not config.exuraSio
|
||||
widget:setOn(config.exuraSio)
|
||||
end
|
||||
sioListWindow.exuraGranSio:setOn(config.exuraGranSio)
|
||||
sioListWindow.exuraGranSio.onClick = function(widget)
|
||||
config.exuraGranSio = not config.exuraGranSio
|
||||
widget:setOn(config.exuraGranSio)
|
||||
end
|
||||
sioListWindow.exuraMasRes:setOn(config.exuraMasRes)
|
||||
sioListWindow.exuraMasRes.onClick = function(widget)
|
||||
config.exuraMasRes = not config.exuraMasRes
|
||||
widget:setOn(config.exuraMasRes)
|
||||
end
|
||||
sioListWindow.vocation.ED:setOn(config.healEd)
|
||||
sioListWindow.vocation.ED.onClick = function(widget)
|
||||
config.healEd = not config.healEd
|
||||
widget:setOn(config.healEd)
|
||||
end
|
||||
sioListWindow.vocation.MS:setOn(config.healMs)
|
||||
sioListWindow.vocation.MS.onClick = function(widget)
|
||||
config.healMs = not config.healMs
|
||||
widget:setOn(config.healMs)
|
||||
end
|
||||
sioListWindow.vocation.EK:setOn(config.healEk)
|
||||
sioListWindow.vocation.EK.onClick = function(widget)
|
||||
config.healEk = not config.healEk
|
||||
widget:setOn(config.healEk)
|
||||
end
|
||||
sioListWindow.vocation.RP:setOn(config.healRp)
|
||||
sioListWindow.vocation.RP.onClick = function(widget)
|
||||
config.healRp = not config.healRp
|
||||
widget:setOn(config.healRp)
|
||||
end
|
||||
|
||||
-- functions
|
||||
local updateMinManaText = function()
|
||||
sioListWindow.manaInfo:setText("Minimum Mana >= " .. config.minMana .. "%")
|
||||
end
|
||||
local updateFriendHpText = function()
|
||||
sioListWindow.friendHp:setText("Heal Friend Below " .. config.minFriendHp .. "% hp")
|
||||
end
|
||||
local updateDistanceText = function()
|
||||
sioListWindow.distText:setText("Max Distance: " .. config.distance)
|
||||
end
|
||||
|
||||
-- scrollbars and text updates
|
||||
sioListWindow.Distance:setValue(config.distance)
|
||||
sioListWindow.Distance.onValueChange = function(scroll, value)
|
||||
config.distance = value
|
||||
updateDistanceText()
|
||||
end
|
||||
updateDistanceText()
|
||||
|
||||
sioListWindow.minMana:setValue(config.minMana)
|
||||
sioListWindow.minMana.onValueChange = function(scroll, value)
|
||||
config.minMana = value
|
||||
updateMinManaText()
|
||||
end
|
||||
updateMinManaText()
|
||||
|
||||
sioListWindow.minFriendHp:setValue(config.minFriendHp)
|
||||
sioListWindow.minFriendHp.onValueChange = function(scroll, value)
|
||||
config.minFriendHp = value
|
||||
updateFriendHpText()
|
||||
end
|
||||
updateFriendHpText()
|
||||
|
||||
sioListWindow.itemId:setItemId(config.id)
|
||||
sioListWindow.itemId.onItemChange = function(widget)
|
||||
config.id = widget:getItemId()
|
||||
end
|
||||
|
||||
sioListWindow.closeButton.onClick = function(widget)
|
||||
sioListWindow:hide()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- local variables
|
||||
local newTibia = g_game.getClientVersion() >= 960
|
||||
|
||||
local function isValid(name)
|
||||
if not newTibia then return true end
|
||||
|
||||
local voc = vBot.BotServerMembers[name]
|
||||
if not voc then return true end
|
||||
|
||||
if voc == 11 then voc = 1
|
||||
elseif voc == 12 then voc = 2
|
||||
elseif voc == 13 then voc = 3
|
||||
elseif voc == 14 then voc = 4
|
||||
end
|
||||
|
||||
local isOk = false
|
||||
if voc == 1 and config.healEk then
|
||||
isOk = true
|
||||
elseif voc == 2 and config.healRp then
|
||||
isOk = true
|
||||
elseif voc == 3 and config.healMs then
|
||||
isOk = true
|
||||
elseif voc == 4 and config.healEd then
|
||||
isOk = true
|
||||
end
|
||||
|
||||
return isOk
|
||||
end
|
||||
|
||||
macro(200, function()
|
||||
if not config.enabled then return end
|
||||
if modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
|
||||
--[[
|
||||
1. custom spell
|
||||
2. exura gran sio - at 50% of minHpValue
|
||||
3. exura gran mas res
|
||||
4. exura sio
|
||||
5. item healing
|
||||
--]]
|
||||
|
||||
-- exura gran sio & custom spell
|
||||
if config.customSpell or config.exuraGranSio then
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) then
|
||||
if config.customSpell and spec:getHealthPercent() <= config.minFriendHp then
|
||||
return cast(config.customSpellName .. ' "' .. spec:getName() .. '"', 1000)
|
||||
end
|
||||
if config.exuraGranSio and spec:getHealthPercent() <= config.minFriendHp/3 then
|
||||
if canCast('exura gran sio "' .. spec:getName() ..'"') then
|
||||
return cast('exura gran sio "' .. spec:getName() ..'"', 60000)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- exura gran mas res and standard sio
|
||||
local friends = 0
|
||||
if config.exuraMasRes then
|
||||
for i, spec in ipairs(getSpectators(player, largeRuneArea)) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) and spec:getHealthPercent() <= config.minFriendHp then
|
||||
friends = friends + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if friends > 1 then
|
||||
return cast('exura gran mas res', 2000)
|
||||
end
|
||||
end
|
||||
if config.exuraSio or config.itemHeal then
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) then
|
||||
if spec:getHealthPercent() <= config.minFriendHp then
|
||||
if config.exuraSio then
|
||||
return cast('exura sio "' .. spec:getName() .. '"', 1000)
|
||||
elseif findItem(config.id) and distanceFromPlayer(spec:getPosition()) <= config.distance then
|
||||
return useWith(config.id, spec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
addSeparator()
|
223
modules/game_bot/default_configs/vBot_4.8/vBot/alarms.lua
Normal file
@ -0,0 +1,223 @@
|
||||
local panelName = "alarms"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Alarms')
|
||||
|
||||
Button
|
||||
id: alerts
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Edit
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
local window = UI.createWindow("AlarmsWindow")
|
||||
window:hide()
|
||||
|
||||
ui.alerts.onClick = function()
|
||||
window:show()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end
|
||||
|
||||
local widgets =
|
||||
{
|
||||
"AlarmCheckBox",
|
||||
"AlarmCheckBoxAndSpinBox",
|
||||
"AlarmCheckBoxAndTextEdit"
|
||||
}
|
||||
|
||||
local parents =
|
||||
{
|
||||
window.list,
|
||||
window.settingsList
|
||||
}
|
||||
|
||||
|
||||
-- type
|
||||
addAlarm = function(id, title, defaultValue, alarmType, parent, tooltip)
|
||||
local widget = UI.createWidget(widgets[alarmType], parents[parent])
|
||||
widget:setId(id)
|
||||
|
||||
if type(config[id]) ~= 'table' then
|
||||
config[id] = {}
|
||||
end
|
||||
|
||||
widget.tick:setText(title)
|
||||
widget.tick:setChecked(config[id].enabled)
|
||||
widget.tick:setTooltip(tooltip)
|
||||
widget.tick.onClick = function()
|
||||
config[id].enabled = not config[id].enabled
|
||||
widget.tick:setChecked(config[id].enabled)
|
||||
end
|
||||
|
||||
if alarmType > 1 and type(config[id].value) == 'nil' then
|
||||
config[id].value = defaultValue
|
||||
end
|
||||
|
||||
if alarmType == 2 then
|
||||
widget.value:setValue(config[id].value)
|
||||
widget.value.onValueChange = function(widget, value)
|
||||
config[id].value = value
|
||||
end
|
||||
elseif alarmType == 3 then
|
||||
widget.text:setText(config[id].value)
|
||||
widget.text.onTextChange = function(widget, newText)
|
||||
config[id].value = newText
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- settings
|
||||
addAlarm("ignoreFriends", "Ignore Friends", true, 1, 2)
|
||||
addAlarm("flashClient", "Flash Client", true, 1, 2)
|
||||
|
||||
-- alarm list
|
||||
addAlarm("damageTaken", "Damage Taken", false, 1, 1)
|
||||
addAlarm("lowHealth", "Low Health", 20, 2, 1)
|
||||
addAlarm("lowMana", "Low Mana", 20, 2, 1)
|
||||
addAlarm("playerAttack", "Player Attack", false, 1, 1)
|
||||
|
||||
UI.Separator(window.list)
|
||||
|
||||
addAlarm("privateMsg", "Private Message", false, 1, 1)
|
||||
addAlarm("defaultMsg", "Default Message", false, 1, 1)
|
||||
addAlarm("customMessage", "Custom Message:", "", 3, 1, "You can add text, that if found in any incoming message will trigger alert.\n You can add many, just separate them by comma.")
|
||||
|
||||
UI.Separator(window.list)
|
||||
|
||||
addAlarm("creatureDetected", "Creature Detected", false, 1, 1)
|
||||
addAlarm("playerDetected", "Player Detected", false, 1, 1)
|
||||
addAlarm("creatureName", "Creature Name:", "", 3, 1, "You can add a name or part of it, that if found in any visible creature name will trigger alert.\nYou can add many, just separate them by comma.")
|
||||
|
||||
|
||||
local lastCall = now
|
||||
local function alarm(file, windowText)
|
||||
if now - lastCall < 2000 then return end -- 2s delay
|
||||
lastCall = now
|
||||
|
||||
if not g_resources.fileExists(file) then
|
||||
file = "/sounds/alarm.ogg"
|
||||
lastCall = now + 4000 -- alarm.ogg length is 6s
|
||||
end
|
||||
|
||||
|
||||
if modules.game_bot.g_app.getOs() == "windows" and config.flashClient.enabled then
|
||||
g_window.flash()
|
||||
end
|
||||
g_window.setTitle(player:getName() .. " - " .. windowText)
|
||||
playSound(file)
|
||||
end
|
||||
|
||||
-- damage taken & custom message
|
||||
onTextMessage(function(mode, text)
|
||||
if not config.enabled then return end
|
||||
if mode == 22 and config.damageTaken.enabled then
|
||||
return alarm('/sounds/magnum.ogg', "Damage Received!")
|
||||
end
|
||||
|
||||
if config.customMessage.enabled then
|
||||
local alertText = config.customMessage.value
|
||||
if alertText:len() > 0 then
|
||||
text = text:lower()
|
||||
local parts = string.split(alertText, ",")
|
||||
|
||||
for i=1,#parts do
|
||||
local part = parts[i]
|
||||
part = part:trim()
|
||||
part = part:lower()
|
||||
|
||||
if text:find(part) then
|
||||
return alarm('/sounds/magnum.ogg', "Special Message!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- default & private message
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if not config.enabled then return end
|
||||
if name == player:getName() then return end -- ignore self messages
|
||||
if config.ignoreFriends.enabled and isFriend(name) then return end -- ignore friends if enabled
|
||||
|
||||
if mode == 1 and config.defaultMsg.enabled then
|
||||
return alarm("/sounds/magnum.ogg", "Default Message!")
|
||||
end
|
||||
|
||||
if mode == 4 and config.privateMsg.enabled then
|
||||
return alarm("/sounds/Private_Message.ogg", "Private Message!")
|
||||
end
|
||||
end)
|
||||
|
||||
-- health & mana
|
||||
macro(100, function()
|
||||
if not config.enabled then return end
|
||||
if config.lowHealth.enabled then
|
||||
if hppercent() < config.lowHealth.value then
|
||||
return alarm("/sounds/Low_Health.ogg", "Low Health!")
|
||||
end
|
||||
end
|
||||
|
||||
if config.lowMana.enabled then
|
||||
if hppercent() < config.lowMana.value then
|
||||
return alarm("/sounds/Low_Mana.ogg", "Low Mana!")
|
||||
end
|
||||
end
|
||||
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if not spec:isLocalPlayer() and not (config.ignoreFriends.enabled and isFriend(spec)) then
|
||||
|
||||
if config.creatureDetected.enabled then
|
||||
return alarm("/sounds/magnum.ogg", "Creature Detected!")
|
||||
end
|
||||
|
||||
if spec:isPlayer() then
|
||||
if spec:isTimedSquareVisible() and config.playerAttack.enabled then
|
||||
return alarm("/sounds/Player_Attack.ogg", "Player Attack!")
|
||||
end
|
||||
if config.playerDetected.enabled then
|
||||
return alarm("/sounds/Player_Detected.ogg", "Player Detected!")
|
||||
end
|
||||
end
|
||||
|
||||
if config.creatureName.enabled then
|
||||
local name = spec:getName():lower()
|
||||
local fragments = string.split(config.creatureName.value, ",")
|
||||
|
||||
for i=1,#fragments do
|
||||
local frag = fragments[i]:trim():lower()
|
||||
|
||||
if name:lower():find(frag) then
|
||||
return alarm("/sounds/alarm.ogg", "Special Creature Detected!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
135
modules/game_bot/default_configs/vBot_4.8/vBot/alarms.otui
Normal file
@ -0,0 +1,135 @@
|
||||
AlarmCheckBox < Panel
|
||||
height: 20
|
||||
margin-top: 2
|
||||
|
||||
CheckBox
|
||||
id: tick
|
||||
anchors.fill: parent
|
||||
margin-top: 4
|
||||
font: verdana-11px-rounded
|
||||
text: Player Attack
|
||||
text-offset: 17 -3
|
||||
|
||||
AlarmCheckBoxAndSpinBox < Panel
|
||||
height: 20
|
||||
margin-top: 2
|
||||
|
||||
CheckBox
|
||||
id: tick
|
||||
anchors.fill: parent
|
||||
anchors.right: next.left
|
||||
margin-top: 4
|
||||
font: verdana-11px-rounded
|
||||
text: Player Attack
|
||||
text-offset: 17 -3
|
||||
|
||||
SpinBox
|
||||
id: value
|
||||
anchors.top: parent.top
|
||||
margin-top: 1
|
||||
margin-bottom: 1
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 40
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
AlarmCheckBoxAndTextEdit < Panel
|
||||
height: 20
|
||||
margin-top: 2
|
||||
|
||||
CheckBox
|
||||
id: tick
|
||||
anchors.fill: parent
|
||||
anchors.right: next.left
|
||||
margin-top: 4
|
||||
font: verdana-11px-rounded
|
||||
text: Creature Name
|
||||
text-offset: 17 -3
|
||||
|
||||
BotTextEdit
|
||||
id: text
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 150
|
||||
font: terminus-10px
|
||||
margin-top: 1
|
||||
margin-bottom: 1
|
||||
|
||||
AlarmsWindow < MainWindow
|
||||
!text: tr('Alarms')
|
||||
size: 330 400
|
||||
padding: 15
|
||||
@onEscape: self:hide()
|
||||
|
||||
FlatPanel
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
anchors.bottom: settingsList.top
|
||||
margin-bottom: 20
|
||||
margin-top: 10
|
||||
layout: verticalBox
|
||||
padding: 10
|
||||
padding-top: 5
|
||||
|
||||
FlatPanel
|
||||
id: settingsList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: separator.top
|
||||
margin-bottom: 5
|
||||
margin-top: 10
|
||||
padding: 5
|
||||
padding-left: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: settingsList.top
|
||||
anchors.left: settingsList.left
|
||||
margin-left: 5
|
||||
width: 200
|
||||
text: Alarms Settings
|
||||
font: verdana-11px-rounded
|
||||
color: #9f5031
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: list.top
|
||||
anchors.left: list.left
|
||||
margin-left: 5
|
||||
width: 200
|
||||
text: Active Alarms
|
||||
font: verdana-11px-rounded
|
||||
color: #9f5031
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
ResizeBorder
|
||||
id: bottomResizeBorder
|
||||
anchors.fill: separator
|
||||
height: 3
|
||||
minimum: 260
|
||||
maximum: 600
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
background: #ffffff88
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-right: 5
|
||||
@onClick: self:getParent():hide()
|
1826
modules/game_bot/default_configs/vBot_4.8/vBot/analyzer.lua
Normal file
514
modules/game_bot/default_configs/vBot_4.8/vBot/analyzer.otui
Normal file
@ -0,0 +1,514 @@
|
||||
BossCreaturePanel < Panel
|
||||
height: 38
|
||||
|
||||
UICreature
|
||||
id: creature
|
||||
size: 35 35
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
old-scaling: true
|
||||
margin-left: 3
|
||||
|
||||
Label
|
||||
id: name
|
||||
anchors.left: creature.right
|
||||
margin: 1
|
||||
margin-left: 5
|
||||
margin-top: 4
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: creature.verticalCenter
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
color: #FFFFFF
|
||||
text: Duke Krule
|
||||
|
||||
Label
|
||||
id: cooldown
|
||||
anchors.left: creature.right
|
||||
margin: 1
|
||||
margin-left: 5
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: creature.verticalCenter
|
||||
font: verdana-11px-rounded
|
||||
text: 19h 20min
|
||||
|
||||
|
||||
SearchPanel < TextEdit
|
||||
placeholder: Type to search
|
||||
margin-top: 1
|
||||
@onClick: modules.client_textedit.show(self)
|
||||
|
||||
Button
|
||||
id: clear
|
||||
anchors.right: parent.right
|
||||
margin-right: -2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 18 18
|
||||
text: X
|
||||
@onClick: |
|
||||
self:getParent():setText("")
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
AnalyzerListPanel < Panel
|
||||
padding-left: 4
|
||||
padding-right: 4
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
|
||||
ListLabel < Label
|
||||
height: 15
|
||||
font: verdana-11px-rounded
|
||||
text-offset: 15 0
|
||||
|
||||
AnalyzerItemsPanel < Panel
|
||||
id: List
|
||||
padding: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 33 33
|
||||
cell-spacing: 1
|
||||
num-columns: 5
|
||||
fit-children: true
|
||||
|
||||
AnalyzerLootItem < UIItem
|
||||
opacity: 0.87
|
||||
height: 37
|
||||
margin-left: 1
|
||||
virtual: true
|
||||
background-color: alpha
|
||||
|
||||
Label
|
||||
id: count
|
||||
font: verdana-11px-rounded
|
||||
color: white
|
||||
opacity: 0.87
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 2
|
||||
text-align: right
|
||||
text: 0
|
||||
|
||||
AnalyzerGraph < UIGraph
|
||||
height: 140
|
||||
capacity: 400
|
||||
line-width: 1
|
||||
color: red
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
margin-right: 5
|
||||
background-color: #383636
|
||||
padding: 5
|
||||
font: verdana-11px-rounded
|
||||
image-source: /images/ui/graph_background
|
||||
|
||||
AnalyzerProgressBar < ProgressBar
|
||||
background-color: green
|
||||
height: 5
|
||||
margin-top: 3
|
||||
phantom: false
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
border: 1 black
|
||||
|
||||
AnalyzerButton < Button
|
||||
height: 22
|
||||
margin-bottom: 2
|
||||
font: verdana-11px-rounded
|
||||
text-offset: 0 4
|
||||
|
||||
MainAnalyzerWindow < MiniWindow
|
||||
id: MainAnalyzerWindow
|
||||
text: Analytics Selector
|
||||
height: 293
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 5
|
||||
padding-right: 5
|
||||
padding-top: 5
|
||||
layout: verticalBox
|
||||
|
||||
AnalyzerButton
|
||||
id: HuntingAnalyzer
|
||||
text: Hunting Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: LootAnalyzer
|
||||
text: Loot Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: SupplyAnalyzer
|
||||
text: Supply Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: ImpactAnalyzer
|
||||
text: Impact Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: XPAnalyzer
|
||||
text: XP Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: DropTracker
|
||||
text: Drop Tracker
|
||||
|
||||
AnalyzerButton
|
||||
id: Stats
|
||||
text: CaveBot Stats
|
||||
color: #74B73E
|
||||
|
||||
AnalyzerButton
|
||||
id: PartyHunt
|
||||
text: Party Hunt
|
||||
color: #3895D3
|
||||
|
||||
AnalyzerButton
|
||||
id: BossTracker
|
||||
text: Boss Cooldowns
|
||||
color: #df3afb
|
||||
|
||||
AnalyzerButton
|
||||
id: Settings
|
||||
text: Features & Settings
|
||||
color: #FABD02
|
||||
|
||||
AnalyzerButton
|
||||
id: ResetSession
|
||||
text: Reset Session
|
||||
color: #FF0000
|
||||
|
||||
HuntingAnalyzer < MiniWindow
|
||||
id: HuntingAnalyzerWindow
|
||||
text: Hunt Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
LootAnalyzer < MiniWindow
|
||||
id: LootAnalyzerWindow
|
||||
text: Loot Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
SupplyAnalyzer < MiniWindow
|
||||
id: SupplyAnalyzerWindow
|
||||
text: Supply Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
ImpactAnalyzer < MiniWindow
|
||||
id: ImpactAnalyzerWindow
|
||||
text: Impact Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
XPAnalyzer < MiniWindow
|
||||
id: XPAnalyzerWindow
|
||||
text: XP Analyzer
|
||||
height: 150
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
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
|
||||
|
||||
CaveBotStats < MiniWindow
|
||||
id: CaveBotStats
|
||||
text: CaveBot Stats
|
||||
height: 200
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 3
|
||||
padding-right: 3
|
||||
padding-top: 1
|
||||
layout: verticalBox
|
||||
|
||||
BossTracker < MiniWindow
|
||||
id: BossTracker
|
||||
text: Boss Cooldowns
|
||||
height: 200
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 3
|
||||
padding-right: 3
|
||||
padding-top: 1
|
||||
layout: verticalBox
|
||||
|
||||
SearchPanel
|
||||
id: search
|
||||
|
||||
FeaturesWindow < MainWindow
|
||||
id: FeaturesWindow
|
||||
size: 250 370
|
||||
padding: 15
|
||||
text: Analyzers Features
|
||||
@onEscape: self:hide()
|
||||
|
||||
TextList
|
||||
id: CustomPrices
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
padding: 1
|
||||
height: 220
|
||||
vertical-scrollbar: CustomPricesScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: CustomPricesScrollBar
|
||||
anchors.top: CustomPrices.top
|
||||
anchors.bottom: CustomPrices.bottom
|
||||
anchors.right: CustomPrices.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
BotItem
|
||||
id: ID
|
||||
anchors.left: CustomPrices.left
|
||||
anchors.top: CustomPrices.bottom
|
||||
margin-top: 5
|
||||
|
||||
SpinBox
|
||||
id: NewPrice
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
width: 100
|
||||
minimum: 0
|
||||
maximum: 1000000000
|
||||
step: 1
|
||||
text-align: center
|
||||
focusable: true
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: CustomPrices.right
|
||||
text: Add
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: ID.right
|
||||
margin-left: 5
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.verticalCenter: ID.top
|
||||
|
||||
HorizontalSeparator
|
||||
id: secondSeparator
|
||||
anchors.left: ID.right
|
||||
margin-left: 5
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.bottom: ID.bottom
|
||||
|
||||
BotSwitch
|
||||
id: LootChannel
|
||||
anchors.left: CustomPrices.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
anchors.top: prev.top
|
||||
margin-top: 20
|
||||
text: Loot Channel
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotSwitch
|
||||
id: RarityFrames
|
||||
anchors.left: parent.horizontalCenter
|
||||
margin-left: 2
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.top: secondSeparator.top
|
||||
margin-top: 20
|
||||
text: Rarity Frames
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
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
|
33
modules/game_bot/default_configs/vBot_4.8/vBot/antiRs.lua
Normal file
@ -0,0 +1,33 @@
|
||||
setDefaultTab("Tools")
|
||||
g_game.cancelAttackAndFollow()
|
||||
|
||||
local frags = 0
|
||||
local unequip = false
|
||||
local m = macro(50, "AntiRS & Msg", function() end)
|
||||
|
||||
function safeExit()
|
||||
CaveBot.setOff()
|
||||
TargetBot.setOff()
|
||||
g_game.cancelAttackAndFollow()
|
||||
g_game.cancelAttackAndFollow()
|
||||
g_game.cancelAttackAndFollow()
|
||||
modules.game_interface.forceExit()
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if not m.isOn() then return end
|
||||
if not text:find("Warning! The murder of") then return end
|
||||
frags = frags + 1
|
||||
if killsToRs() < 6 or frags > 1 then
|
||||
EquipManager.setOff()
|
||||
schedule(100, function()
|
||||
local id = getLeft() and getLeft():getId()
|
||||
|
||||
if id and not unequip then
|
||||
unequip = true
|
||||
g_game.equipItemId(id)
|
||||
end
|
||||
safeExit()
|
||||
end)
|
||||
end
|
||||
end)
|
22
modules/game_bot/default_configs/vBot_4.8/vBot/cast_food.lua
Normal file
@ -0,0 +1,22 @@
|
||||
setDefaultTab("HP")
|
||||
if voc() ~= 1 and voc() ~= 11 then
|
||||
if storage.foodItems then
|
||||
local t = {}
|
||||
for i, v in pairs(storage.foodItems) do
|
||||
if not table.find(t, v.id) then
|
||||
table.insert(t, v.id)
|
||||
end
|
||||
end
|
||||
local foodItems = { 3607, 3585, 3592, 3600, 3601 }
|
||||
for i, item in pairs(foodItems) do
|
||||
if not table.find(t, item) then
|
||||
table.insert(storage.foodItems, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
macro(500, "Cast Food", function()
|
||||
if player:getRegenerationTime() <= 400 then
|
||||
cast("exevo pan", 5000)
|
||||
end
|
||||
end)
|
||||
end
|
53
modules/game_bot/default_configs/vBot_4.8/vBot/cavebot.lua
Normal file
@ -0,0 +1,53 @@
|
||||
-- Cavebot by otclient@otclient.ovh
|
||||
-- visit http://bot.otclient.ovh/
|
||||
|
||||
local cavebotTab = "Cave"
|
||||
local targetingTab = storage.extras.joinBot and "Cave" or "Target"
|
||||
|
||||
setDefaultTab(cavebotTab)
|
||||
CaveBot.Extensions = {}
|
||||
importStyle("/cavebot/cavebot.otui")
|
||||
importStyle("/cavebot/config.otui")
|
||||
importStyle("/cavebot/editor.otui")
|
||||
dofile("/cavebot/actions.lua")
|
||||
dofile("/cavebot/config.lua")
|
||||
dofile("/cavebot/editor.lua")
|
||||
dofile("/cavebot/example_functions.lua")
|
||||
dofile("/cavebot/recorder.lua")
|
||||
dofile("/cavebot/walking.lua")
|
||||
dofile("/cavebot/minimap.lua")
|
||||
-- in this section you can add extensions, check extension_template.lua
|
||||
--dofile("/cavebot/extension_template.lua")
|
||||
dofile("/cavebot/sell_all.lua")
|
||||
dofile("/cavebot/depositor.lua")
|
||||
dofile("/cavebot/buy_supplies.lua")
|
||||
dofile("/cavebot/d_withdraw.lua")
|
||||
dofile("/cavebot/supply_check.lua")
|
||||
dofile("/cavebot/travel.lua")
|
||||
dofile("/cavebot/doors.lua")
|
||||
dofile("/cavebot/pos_check.lua")
|
||||
dofile("/cavebot/withdraw.lua")
|
||||
dofile("/cavebot/inbox_withdraw.lua")
|
||||
dofile("/cavebot/lure.lua")
|
||||
dofile("/cavebot/bank.lua")
|
||||
dofile("/cavebot/clear_tile.lua")
|
||||
dofile("/cavebot/tasker.lua")
|
||||
dofile("/cavebot/imbuing.lua")
|
||||
dofile("/cavebot/stand_lure.lua")
|
||||
-- main cavebot file, must be last
|
||||
dofile("/cavebot/cavebot.lua")
|
||||
|
||||
setDefaultTab(targetingTab)
|
||||
if storage.extras.joinBot then UI.Label("-- [[ TargetBot ]] --") end
|
||||
TargetBot = {} -- global namespace
|
||||
importStyle("/targetbot/looting.otui")
|
||||
importStyle("/targetbot/target.otui")
|
||||
importStyle("/targetbot/creature_editor.otui")
|
||||
dofile("/targetbot/creature.lua")
|
||||
dofile("/targetbot/creature_attack.lua")
|
||||
dofile("/targetbot/creature_editor.lua")
|
||||
dofile("/targetbot/creature_priority.lua")
|
||||
dofile("/targetbot/looting.lua")
|
||||
dofile("/targetbot/walking.lua")
|
||||
-- main targetbot file, must be last
|
||||
dofile("/targetbot/target.lua")
|
@ -0,0 +1,63 @@
|
||||
setDefaultTab("Cave")
|
||||
|
||||
g_ui.loadUIFromString([[
|
||||
CaveBotControlPanel < Panel
|
||||
margin-top: 5
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Control Panel
|
||||
font: verdana-11px-rounded
|
||||
margin-top: 3
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 86 20
|
||||
cell-spacing: 1
|
||||
flow: true
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 3
|
||||
]])
|
||||
|
||||
local panel = UI.createWidget("CaveBotControlPanel")
|
||||
|
||||
storage.caveBot = {
|
||||
forceRefill = false,
|
||||
backStop = false,
|
||||
backTrainers = false,
|
||||
backOffline = false
|
||||
}
|
||||
|
||||
-- [[ B U T T O N S ]] --
|
||||
|
||||
local forceRefill = UI.Button("Force Refill", function(widget)
|
||||
storage.caveBot.forceRefill = true
|
||||
print("[CaveBot] Going back on refill on next supply check.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backStop = UI.Button("Back & Stop", function(widget)
|
||||
storage.caveBot.backStop = true
|
||||
print("[CaveBot] Going back to city on next supply check and turning off CaveBot on depositer action.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backTrainers = UI.Button("To Trainers", function(widget)
|
||||
storage.caveBot.backTrainers = true
|
||||
print("[CaveBot] Going back to city on next supply check and going to label 'toTrainers' on depositer action.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backOffline = UI.Button("Offline", function(widget)
|
||||
storage.caveBot.backOffline = true
|
||||
print("[CaveBot] Going back to city on next supply check and going to label 'toOfflineTraining' on depositer action.")
|
||||
end, panel.buttons)
|
443
modules/game_bot/default_configs/vBot_4.8/vBot/combo.lua
Normal file
@ -0,0 +1,443 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "combobot"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('ComboBot')
|
||||
|
||||
Button
|
||||
id: combos
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
onSayEnabled = false,
|
||||
onShootEnabled = false,
|
||||
onCastEnabled = false,
|
||||
followLeaderEnabled = false,
|
||||
attackLeaderTargetEnabled = false,
|
||||
attackSpellEnabled = false,
|
||||
attackItemToggle = false,
|
||||
sayLeader = "",
|
||||
shootLeader = "",
|
||||
castLeader = "",
|
||||
sayPhrase = "",
|
||||
spell = "",
|
||||
serverLeader = "",
|
||||
item = 3155,
|
||||
attack = "",
|
||||
follow = "",
|
||||
commandsEnabled = true,
|
||||
serverEnabled = false,
|
||||
serverLeaderTarget = false,
|
||||
serverTriggers = true
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
ui.combos.onClick = function(widget)
|
||||
comboWindow:show()
|
||||
comboWindow:raise()
|
||||
comboWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
comboWindow = UI.createWindow('ComboWindow', rootWidget)
|
||||
comboWindow:hide()
|
||||
|
||||
-- bot item
|
||||
|
||||
comboWindow.actions.attackItem:setItemId(config.item)
|
||||
comboWindow.actions.attackItem.onItemChange = function(widget)
|
||||
config.item = widget:getItemId()
|
||||
end
|
||||
|
||||
-- switches
|
||||
|
||||
comboWindow.actions.commandsToggle:setOn(config.commandsEnabled)
|
||||
comboWindow.actions.commandsToggle.onClick = function(widget)
|
||||
config.commandsEnabled = not config.commandsEnabled
|
||||
widget:setOn(config.commandsEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.botServerToggle:setOn(config.serverEnabled)
|
||||
comboWindow.server.botServerToggle.onClick = function(widget)
|
||||
config.serverEnabled = not config.serverEnabled
|
||||
widget:setOn(config.serverEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.Triggers:setOn(config.serverTriggers)
|
||||
comboWindow.server.Triggers.onClick = function(widget)
|
||||
config.serverTriggers = not config.serverTriggers
|
||||
widget:setOn(config.serverTriggers)
|
||||
end
|
||||
|
||||
comboWindow.server.targetServerLeaderToggle:setOn(config.serverLeaderTarget)
|
||||
comboWindow.server.targetServerLeaderToggle.onClick = function(widget)
|
||||
config.serverLeaderTarget = not config.serverLeaderTarget
|
||||
widget:setOn(config.serverLeaderTarget)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
comboWindow.closeButton.onClick = function(widget)
|
||||
comboWindow:hide()
|
||||
end
|
||||
|
||||
-- combo boxes
|
||||
|
||||
comboWindow.actions.followLeader:setOption(config.follow)
|
||||
comboWindow.actions.followLeader.onOptionChange = function(widget)
|
||||
config.follow = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTarget:setOption(config.attack)
|
||||
comboWindow.actions.attackLeaderTarget.onOptionChange = function(widget)
|
||||
config.attack = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
comboWindow.trigger.onSayToggle:setChecked(config.onSayEnabled)
|
||||
comboWindow.trigger.onSayToggle.onClick = function(widget)
|
||||
config.onSayEnabled = not config.onSayEnabled
|
||||
widget:setChecked(config.onSayEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootToggle:setChecked(config.onShootEnabled)
|
||||
comboWindow.trigger.onShootToggle.onClick = function(widget)
|
||||
config.onShootEnabled = not config.onShootEnabled
|
||||
widget:setChecked(config.onShootEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastToggle:setChecked(config.onCastEnabled)
|
||||
comboWindow.trigger.onCastToggle.onClick = function(widget)
|
||||
config.onCastEnabled = not config.onCastEnabled
|
||||
widget:setChecked(config.onCastEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.followLeaderToggle:setChecked(config.followLeaderEnabled)
|
||||
comboWindow.actions.followLeaderToggle.onClick = function(widget)
|
||||
config.followLeaderEnabled = not config.followLeaderEnabled
|
||||
widget:setChecked(config.followLeaderEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTargetToggle:setChecked(config.attackLeaderTargetEnabled)
|
||||
comboWindow.actions.attackLeaderTargetToggle.onClick = function(widget)
|
||||
config.attackLeaderTargetEnabled = not config.attackLeaderTargetEnabled
|
||||
widget:setChecked(config.attackLeaderTargetEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpellToggle:setChecked(config.attackSpellEnabled)
|
||||
comboWindow.actions.attackSpellToggle.onClick = function(widget)
|
||||
config.attackSpellEnabled = not config.attackSpellEnabled
|
||||
widget:setChecked(config.attackSpellEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackItemToggle:setChecked(config.attackItemEnabled)
|
||||
comboWindow.actions.attackItemToggle.onClick = function(widget)
|
||||
config.attackItemEnabled = not config.attackItemEnabled
|
||||
widget:setChecked(config.attackItemEnabled)
|
||||
end
|
||||
|
||||
-- text edits
|
||||
comboWindow.trigger.onSayLeader:setText(config.sayLeader)
|
||||
comboWindow.trigger.onSayLeader.onTextChange = function(widget, text)
|
||||
config.sayLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootLeader:setText(config.shootLeader)
|
||||
comboWindow.trigger.onShootLeader.onTextChange = function(widget, text)
|
||||
config.shootLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastLeader:setText(config.castLeader)
|
||||
comboWindow.trigger.onCastLeader.onTextChange = function(widget, text)
|
||||
config.castLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onSayPhrase:setText(config.sayPhrase)
|
||||
comboWindow.trigger.onSayPhrase.onTextChange = function(widget, text)
|
||||
config.sayPhrase = text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpell:setText(config.spell)
|
||||
comboWindow.actions.attackSpell.onTextChange = function(widget, text)
|
||||
config.spell = text
|
||||
end
|
||||
|
||||
comboWindow.server.botServerLeader:setText(config.serverLeader)
|
||||
comboWindow.server.botServerLeader.onTextChange = function(widget, text)
|
||||
config.serverLeader = text
|
||||
end
|
||||
end
|
||||
|
||||
-- bot server
|
||||
-- [[ join party made by Frosty ]] --
|
||||
|
||||
local shouldCloseWindow = false
|
||||
local firstInvitee = true
|
||||
local isInComboTeam = false
|
||||
macro(10, function()
|
||||
if shouldCloseWindow and config.serverEnabled and config.enabled then
|
||||
local channelsWindow = modules.game_console.channelsWindow
|
||||
if channelsWindow then
|
||||
local child = channelsWindow:getChildById("buttonCancel")
|
||||
if child then
|
||||
child:onClick()
|
||||
shouldCloseWindow = false
|
||||
isInComboTeam = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
comboWindow.server.partyButton.onClick = function(widget)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if config.serverLeader:len() > 0 and storage.BotServerChannel:len() > 0 then
|
||||
talkPrivate(config.serverLeader, "request invite " .. storage.BotServerChannel)
|
||||
else
|
||||
error("Request failed. Lack of data.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if mode == 20 then
|
||||
if string.find(text, "invited you to") then
|
||||
local regex = "[a-zA-Z]*"
|
||||
local regexData = regexMatch(text, regex)
|
||||
if regexData[1][1]:lower() == config.serverLeader:lower() then
|
||||
local leader = getCreatureByName(regexData[1][1])
|
||||
if leader then
|
||||
g_game.partyJoin(leader:getId())
|
||||
g_game.requestChannels()
|
||||
g_game.joinChannel(1)
|
||||
shouldCloseWindow = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if mode == 4 then
|
||||
if string.find(text, "request invite") then
|
||||
local access = string.match(text, "%d.*")
|
||||
if access and access == storage.BotServerChannel then
|
||||
local minion = getCreatureByName(name)
|
||||
if minion then
|
||||
g_game.partyInvite(minion:getId())
|
||||
if firstInvitee then
|
||||
g_game.requestChannels()
|
||||
g_game.joinChannel(1)
|
||||
shouldCloseWindow = true
|
||||
firstInvitee = false
|
||||
end
|
||||
end
|
||||
else
|
||||
talkPrivate(name, "Incorrect access key!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- [[ End of Frosty's Code ]] --
|
||||
if config.enabled and config.enabled then
|
||||
if name:lower() == config.sayLeader:lower() and string.find(text, config.sayPhrase) and config.onSayEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
if (config.castLeader and name:lower() == config.castLeader:lower()) and isAttSpell(text) and config.onCastEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
end
|
||||
if config.enabled and config.commandsEnabled and (config.shootLeader and name:lower() == config.shootLeader:lower()) or (config.sayLeader and name:lower() == config.sayLeader:lower()) or (config.castLeader and name:lower() == config.castLeader:lower()) then
|
||||
if string.find(text, "ue") then
|
||||
say(config.spell)
|
||||
elseif string.find(text, "sd") then
|
||||
local params = string.split(text, ",")
|
||||
if #params == 2 then
|
||||
local target = params[2]:trim()
|
||||
if getCreatureByName(target) then
|
||||
useWith(3155, getCreatureByName(target))
|
||||
end
|
||||
end
|
||||
elseif string.find(text, "att") then
|
||||
local attParams = string.split(text, ",")
|
||||
if #attParams == 2 then
|
||||
local atTarget = attParams[2]:trim()
|
||||
if getCreatureByName(atTarget) and config.attack == "COMMAND TARGET" then
|
||||
g_game.attack(getCreatureByName(atTarget))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if isAttSpell(text) and config.enabled and config.serverEnabled then
|
||||
BotServer.send("trigger", "start")
|
||||
end
|
||||
end)
|
||||
|
||||
onMissle(function(missle)
|
||||
if config.enabled and config.onShootEnabled then
|
||||
if not config.shootLeader or config.shootLeader:len() == 0 then
|
||||
return
|
||||
end
|
||||
local src = missle:getSource()
|
||||
if src.z ~= posz() then
|
||||
return
|
||||
end
|
||||
local from = g_map.getTile(src)
|
||||
local to = g_map.getTile(missle:getDestination())
|
||||
if not from or not to then
|
||||
return
|
||||
end
|
||||
local fromCreatures = from:getCreatures()
|
||||
local toCreatures = to:getCreatures()
|
||||
if #fromCreatures ~= 1 or #toCreatures ~= 1 then
|
||||
return
|
||||
end
|
||||
local c1 = fromCreatures[1]
|
||||
local t1 = toCreatures[1]
|
||||
leaderTarget = t1
|
||||
if c1:getName():lower() == config.shootLeader:lower() then
|
||||
if config.attackItemEnabled and config.item and config.item > 100 and findItem(config.item) then
|
||||
useWith(config.item, t1)
|
||||
end
|
||||
if config.attackSpellEnabled and config.spell:len() > 1 then
|
||||
say(config.spell)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
macro(10, function()
|
||||
if not config.enabled or not config.attackLeaderTargetEnabled then return end
|
||||
if leaderTarget and config.attack == "LEADER TARGET" then
|
||||
if not getTarget() or (getTarget() and getTarget():getName() ~= leaderTarget:getName()) then
|
||||
g_game.attack(leaderTarget)
|
||||
end
|
||||
end
|
||||
if config.enabled and config.serverEnabled and config.attack == "SERVER LEADER TARGET" and serverTarget then
|
||||
if serverTarget and not getTarget() or (getTarget() and getTarget():getname() ~= serverTarget)
|
||||
then
|
||||
g_game.attack(serverTarget)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local toFollow
|
||||
local toFollowPos = {}
|
||||
|
||||
macro(100, function()
|
||||
toFollow = nil
|
||||
if not config.enabled or not config.followLeaderEnabled then return end
|
||||
if leaderTarget and config.follow == "LEADER TARGET" and leaderTarget:isPlayer() then
|
||||
toFollow = leaderTarget:getName()
|
||||
elseif config.follow == "SERVER LEADER TARGET" and config.serverLeader:len() ~= 0 then
|
||||
toFollow = serverTarget
|
||||
elseif config.follow == "SERVER LEADER" and config.serverLeader:len() ~= 0 then
|
||||
toFollow = config.serverLeader
|
||||
elseif config.follow == "LEADER" then
|
||||
if config.onSayEnabled and config.sayLeader:len() ~= 0 then
|
||||
toFollow = config.sayLeader
|
||||
elseif config.onCastEnabled and config.castLeader:len() ~= 0 then
|
||||
toFollow = config.castLeader
|
||||
elseif config.onShootEnabled and config.shootLeader:len() ~= 0 then
|
||||
toFollow = config.shootLeader
|
||||
end
|
||||
end
|
||||
if not toFollow then return end
|
||||
local target = getCreatureByName(toFollow)
|
||||
if target then
|
||||
local tpos = target:getPosition()
|
||||
toFollowPos[tpos.z] = tpos
|
||||
end
|
||||
if player:isWalking() then return end
|
||||
local p = toFollowPos[posz()]
|
||||
if not p then return end
|
||||
if CaveBot.walkTo(p, 20, {ignoreNonPathable=true, precision=1, ignoreStairs=false}) then
|
||||
delay(100)
|
||||
end
|
||||
end)
|
||||
|
||||
onCreaturePositionChange(function(creature, oldPos, newPos)
|
||||
if creature:getName() == toFollow and newPos then
|
||||
toFollowPos[newPos.z] = newPos
|
||||
end
|
||||
end)
|
||||
|
||||
local timeout = now
|
||||
macro(10, function()
|
||||
if config.enabled and startCombo then
|
||||
if config.attackItemEnabled and config.item and config.item > 100 and findItem(config.item) then
|
||||
useWith(config.item, getTarget())
|
||||
end
|
||||
if config.attackSpellEnabled and config.spell:len() > 1 then
|
||||
say(config.spell)
|
||||
end
|
||||
startCombo = false
|
||||
end
|
||||
-- attack part / server
|
||||
if BotServer._websocket and config.enabled and config.serverEnabled then
|
||||
if target() and now - timeout > 500 then
|
||||
targetPos = target():getName()
|
||||
BotServer.send("target", targetPos)
|
||||
timeout = now
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if BotServer._websocket and itemId == 3155 then
|
||||
BotServer.send("useWith", target:getPosition())
|
||||
end
|
||||
end)
|
||||
|
||||
if BotServer._websocket and config.enabled and config.serverEnabled then
|
||||
BotServer.listen("trigger", function(name, message)
|
||||
if message == "start" and name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() and config.serverTriggers then
|
||||
startCombo = true
|
||||
end
|
||||
end)
|
||||
BotServer.listen("target", function(name, message)
|
||||
if name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() then
|
||||
if not target() or target():getName() == getCreatureByName(message) then
|
||||
if config.serverLeaderTarget then
|
||||
serverTarget = getCreatureByName(message)
|
||||
g_game.attack(getCreatureByName(message))
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
BotServer.listen("useWith", function(name, message)
|
||||
local tile = g_map.getTile(message)
|
||||
if config.serverTriggers and name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() and config.attackItemEnabled and config.item and findItem(config.item) then
|
||||
useWith(config.item, tile:getTopUseThing())
|
||||
end
|
||||
end)
|
||||
end
|
391
modules/game_bot/default_configs/vBot_4.8/vBot/combo.otui
Normal file
@ -0,0 +1,391 @@
|
||||
AttackComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
AttackComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
AttackComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("LEADER TARGET")
|
||||
self:addOption("COMMAND TARGET")
|
||||
|
||||
FollowComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
FollowComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
FollowComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("LEADER TARGET")
|
||||
self:addOption("SERVER LEADER TARGET")
|
||||
self:addOption("LEADER")
|
||||
self:addOption("SERVER LEADER")
|
||||
|
||||
ComboTrigger < Panel
|
||||
id: trigger
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 450 72
|
||||
|
||||
Label
|
||||
id: triggerLabel1
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: On Say
|
||||
margin-top: 8
|
||||
margin-left: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel
|
||||
anchors.left: triggerLabel1.right
|
||||
anchors.top: triggerLabel1.top
|
||||
text: Leader:
|
||||
margin-left: 35
|
||||
|
||||
TextEdit
|
||||
id: onSayLeader
|
||||
anchors.left: leaderLabel.right
|
||||
anchors.top: leaderLabel.top
|
||||
anchors.bottom: leaderLabel.bottom
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
Label
|
||||
id: phrase
|
||||
anchors.left: onSayLeader.right
|
||||
anchors.top: onSayLeader.top
|
||||
text: Phrase:
|
||||
margin-left: 5
|
||||
|
||||
TextEdit
|
||||
id: onSayPhrase
|
||||
anchors.left: phrase.right
|
||||
anchors.top: leaderLabel.top
|
||||
anchors.bottom: leaderLabel.bottom
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onSayToggle
|
||||
anchors.left: onSayPhrase.right
|
||||
anchors.top: onSayPhrase.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: triggerLabel2
|
||||
anchors.left: triggerLabel1.left
|
||||
anchors.top: triggerLabel1.bottom
|
||||
text: On Shoot
|
||||
margin-top: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel1
|
||||
anchors.left: triggerLabel2.right
|
||||
anchors.top: triggerLabel2.top
|
||||
text: Leader:
|
||||
margin-left: 24
|
||||
|
||||
TextEdit
|
||||
id: onShootLeader
|
||||
anchors.left: leaderLabel1.right
|
||||
anchors.top: leaderLabel1.top
|
||||
anchors.bottom: leaderLabel1.bottom
|
||||
anchors.right: onSayPhrase.right
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onShootToggle
|
||||
anchors.left: onShootLeader.right
|
||||
anchors.top: onShootLeader.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: triggerLabel3
|
||||
anchors.left: triggerLabel2.left
|
||||
anchors.top: triggerLabel2.bottom
|
||||
text: On Cast
|
||||
margin-top: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel2
|
||||
anchors.left: triggerLabel3.right
|
||||
anchors.top: triggerLabel3.top
|
||||
text: Leader:
|
||||
margin-left: 32
|
||||
|
||||
TextEdit
|
||||
id: onCastLeader
|
||||
anchors.left: leaderLabel2.right
|
||||
anchors.top: leaderLabel2.top
|
||||
anchors.bottom: leaderLabel2.bottom
|
||||
anchors.right: onSayPhrase.right
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onCastToggle
|
||||
anchors.left: onCastLeader.right
|
||||
anchors.top: onCastLeader.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
ComboActions < Panel
|
||||
id: actions
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 220 100
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: Follow:
|
||||
margin-top: 5
|
||||
margin-left: 3
|
||||
height: 15
|
||||
color: #ffaa00
|
||||
|
||||
FollowComboBox
|
||||
id: followLeader
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 7
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: followLeaderToggle
|
||||
anchors.left: followLeader.right
|
||||
anchors.top: followLeader.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 5
|
||||
text: Attack:
|
||||
color: #ffaa00
|
||||
|
||||
AttackComboBox
|
||||
id: attackLeaderTarget
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 5
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: attackLeaderTargetToggle
|
||||
anchors.left: attackLeaderTarget.right
|
||||
anchors.top: attackLeaderTarget.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label2.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 5
|
||||
text: Spell:
|
||||
color: #ffaa00
|
||||
|
||||
TextEdit
|
||||
id: attackSpell
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: attackLeaderTarget.right
|
||||
margin-left: 17
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: attackSpellToggle
|
||||
anchors.left: attackSpell.right
|
||||
anchors.top: attackSpell.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 15
|
||||
text: Attack Item:
|
||||
color: #ffaa00
|
||||
|
||||
BotItem
|
||||
id: attackItem
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 10
|
||||
|
||||
CheckBox
|
||||
id: attackItemToggle
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
BotSwitch
|
||||
id: commandsToggle
|
||||
anchors.left: prev.right
|
||||
anchors.top: attackItem.top
|
||||
anchors.right: attackSpellToggle.right
|
||||
anchors.bottom: attackItem.bottom
|
||||
margin-left: 5
|
||||
text: Leader Commands
|
||||
text-wrap: true
|
||||
multiline: true
|
||||
|
||||
BotServer < Panel
|
||||
id: server
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 220 100
|
||||
|
||||
Label
|
||||
id: labelX
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: Leader:
|
||||
height: 15
|
||||
color: #ffaa00
|
||||
margin-left: 3
|
||||
margin-top: 5
|
||||
|
||||
TextEdit
|
||||
id: botServerLeader
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
margin-right: 3
|
||||
margin-left: 9
|
||||
height: 15
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: partyButton
|
||||
anchors.left: labelX.left
|
||||
anchors.top: botServerLeader.bottom
|
||||
margin-top: 5
|
||||
height: 30
|
||||
text: Join Party
|
||||
text-wrap: true
|
||||
multiline: true
|
||||
|
||||
BotSwitch
|
||||
id: botServerToggle
|
||||
anchors.left: prev.right
|
||||
anchors.top: botServerLeader.bottom
|
||||
anchors.right: parent.right
|
||||
height: 30
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
margin-top: 5
|
||||
text: Server Enabled
|
||||
|
||||
BotSwitch
|
||||
id: targetServerLeaderToggle
|
||||
anchors.left: partyButton.left
|
||||
anchors.top: partyButton.bottom
|
||||
anchors.right: partyButton.right
|
||||
margin-top: 3
|
||||
height: 30
|
||||
text: Leader Targets
|
||||
|
||||
BotSwitch
|
||||
id: Triggers
|
||||
anchors.left: prev.right
|
||||
anchors.top: partyButton.bottom
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
height: 30
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
text: Triggers
|
||||
|
||||
ComboWindow < MainWindow
|
||||
!text: tr('Combo Options')
|
||||
size: 500 280
|
||||
@onEscape: self:hide()
|
||||
|
||||
ComboTrigger
|
||||
id: trigger
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
text: Combo Trigger
|
||||
color: #ff7700
|
||||
|
||||
ComboActions
|
||||
id: actions
|
||||
anchors.top: trigger.bottom
|
||||
anchors.left: trigger.left
|
||||
margin-top: 15
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
margin-top: 85
|
||||
text: Combo Actions
|
||||
color: #ff7700
|
||||
|
||||
BotServer
|
||||
id: server
|
||||
anchors.top: actions.top
|
||||
anchors.left: actions.right
|
||||
margin-left: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: server.left
|
||||
margin-left: 3
|
||||
margin-top: 85
|
||||
text: BotServer
|
||||
color: #ff7700
|
||||
|
||||
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
|
||||
|
||||
Button
|
||||
id: toolsButton
|
||||
!text: tr('Help')
|
||||
font: cipsoftFont
|
||||
anchors.right: closeButton.left
|
||||
anchors.top: closeButton.top
|
||||
margin-right: 10
|
||||
size: 45 21
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/books/scripts/page/combobot")
|
97
modules/game_bot/default_configs/vBot_4.8/vBot/configs.lua
Normal file
@ -0,0 +1,97 @@
|
||||
--[[
|
||||
Configs for modules
|
||||
Based on Kondrah storage method
|
||||
--]]
|
||||
local configName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
|
||||
-- make vBot config dir
|
||||
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/profile_".. profile .. "/HealBot.json"
|
||||
AttackBotConfig = {}
|
||||
local attackBotFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/AttackBot.json"
|
||||
SuppliesConfig = {}
|
||||
local suppliesFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/Supplies.json"
|
||||
|
||||
|
||||
--healbot
|
||||
if g_resources.fileExists(healBotFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(healBotFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. healBotFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
HealBotConfig = result
|
||||
end
|
||||
|
||||
--attackbot
|
||||
if g_resources.fileExists(attackBotFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(attackBotFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. attackBotFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
AttackBotConfig = result
|
||||
end
|
||||
|
||||
--supplies
|
||||
if g_resources.fileExists(suppliesFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(suppliesFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. suppliesFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
SuppliesConfig = result
|
||||
end
|
||||
|
||||
function vBotConfigSave(file)
|
||||
-- file can be either
|
||||
--- heal
|
||||
--- atk
|
||||
--- supply
|
||||
local configFile
|
||||
local configTable
|
||||
if not file then return end
|
||||
file = file:lower()
|
||||
if file == "heal" then
|
||||
configFile = healBotFile
|
||||
configTable = HealBotConfig
|
||||
elseif file == "atk" then
|
||||
configFile = attackBotFile
|
||||
configTable = AttackBotConfig
|
||||
elseif file == "supply" then
|
||||
configFile = suppliesFile
|
||||
configTable = SuppliesConfig
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local status, result = pcall(function()
|
||||
return json.encode(configTable, 2)
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while saving config. it won't be saved. Details: " .. result)
|
||||
end
|
||||
|
||||
if result:len() > 100 * 1024 * 1024 then
|
||||
return onError("config file is too big, above 100MB, it won't be saved")
|
||||
end
|
||||
|
||||
g_resources.writeFileContents(configFile, result)
|
||||
end
|
@ -0,0 +1,136 @@
|
||||
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
|
||||
|
||||
UI.Separator()
|
||||
UI.Label("Sell Exeptions")
|
||||
|
||||
if type(storage.cavebotSell) ~= "table" then
|
||||
storage.cavebotSell = {23544, 3081}
|
||||
end
|
||||
|
||||
local sellContainer = UI.Container(function(widget, items)
|
||||
storage.cavebotSell = items
|
||||
end, true)
|
||||
sellContainer:setHeight(35)
|
||||
sellContainer:setItems(storage.cavebotSell)
|
@ -0,0 +1,98 @@
|
||||
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
|
||||
|
||||
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
|
@ -0,0 +1,76 @@
|
||||
-- config
|
||||
setDefaultTab("Tools")
|
||||
local defaultBp = "shopping bag"
|
||||
local id = 21411
|
||||
|
||||
-- script
|
||||
|
||||
local playerContainer = nil
|
||||
local depotContainer = nil
|
||||
local mailContainer = nil
|
||||
|
||||
function reopenLootContainer()
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == defaultBp:lower() then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
local lootItem = findItem(id)
|
||||
if lootItem then
|
||||
schedule(500, function() g_game.open(lootItem) end)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
macro(50, "Depot Withdraw", function()
|
||||
|
||||
-- set the containers
|
||||
if not potionsContainer or not runesContainer or not ammoContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName() == defaultBp then
|
||||
playerContainer = container
|
||||
elseif string.find(container:getName(), "Depot") then
|
||||
depotContainer = container
|
||||
elseif string.find(container:getName(), "your inbox") then
|
||||
mailContainer = container
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if playerContainer and #playerContainer:getItems() == 20 then
|
||||
for j, item in pairs(playerContainer:getItems()) do
|
||||
if item:getId() == id then
|
||||
g_game.open(item, playerContainer)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if playerContainer and freecap() >= 200 then
|
||||
local time = 500
|
||||
if depotContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName(), "Depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
g_game.move(item, playerContainer:getSlotPosition(playerContainer:getItemsCount()), item:getCount())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if mailContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName(), "your inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
g_game.move(item, playerContainer:getSlotPosition(playerContainer:getItemsCount()), item:getCount())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
48
modules/game_bot/default_configs/vBot_4.8/vBot/eat_food.lua
Normal file
@ -0,0 +1,48 @@
|
||||
setDefaultTab("HP")
|
||||
if voc() ~= 1 and voc() ~= 11 then
|
||||
if storage.foodItems then
|
||||
local t = {}
|
||||
for i, v in pairs(storage.foodItems) do
|
||||
if not table.find(t, v.id) then
|
||||
table.insert(t, v.id)
|
||||
end
|
||||
end
|
||||
local foodItems = { 3607, 3585, 3592, 3600, 3601 }
|
||||
for i, item in pairs(foodItems) do
|
||||
if not table.find(t, item) then
|
||||
table.insert(storage.foodItems, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
macro(500, "Cast Food", function()
|
||||
if player:getRegenerationTime() <= 400 then
|
||||
cast("exevo pan", 5000)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
UI.Label("Eatable items:")
|
||||
if type(storage.foodItems) ~= "table" then
|
||||
storage.foodItems = {3582, 3577}
|
||||
end
|
||||
|
||||
local foodContainer = UI.Container(function(widget, items)
|
||||
storage.foodItems = items
|
||||
end, true)
|
||||
foodContainer:setHeight(35)
|
||||
foodContainer:setItems(storage.foodItems)
|
||||
|
||||
macro(500, "Eat Food", function()
|
||||
if player:getRegenerationTime() > 400 or not storage.foodItems[1] then return end
|
||||
-- search for food in containers
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
for i, foodItem in ipairs(storage.foodItems) do
|
||||
if item:getId() == foodItem.id then
|
||||
return g_game.use(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
UI.Separator()
|
36
modules/game_bot/default_configs/vBot_4.8/vBot/equip.lua
Normal file
@ -0,0 +1,36 @@
|
||||
-- config
|
||||
setDefaultTab("HP")
|
||||
local scripts = 2 -- if you want more auto equip panels you can change 2 to higher value
|
||||
|
||||
-- script by kondrah, don't edit below unless you know what you are doing
|
||||
UI.Label("Auto equip")
|
||||
if type(storage.autoEquip) ~= "table" then
|
||||
storage.autoEquip = {}
|
||||
end
|
||||
for i=1,scripts do
|
||||
if not storage.autoEquip[i] then
|
||||
storage.autoEquip[i] = {on=false, title="Auto Equip", item1=i == 1 and 3052 or 0, item2=i == 1 and 3089 or 0, slot=i == 1 and 9 or 0}
|
||||
end
|
||||
UI.TwoItemsAndSlotPanel(storage.autoEquip[i], function(widget, newParams)
|
||||
storage.autoEquip[i] = newParams
|
||||
end)
|
||||
end
|
||||
macro(250, function()
|
||||
local containers = g_game.getContainers()
|
||||
for index, autoEquip in ipairs(storage.autoEquip) do
|
||||
if autoEquip.on then
|
||||
local slotItem = getSlot(autoEquip.slot)
|
||||
if not slotItem or (slotItem:getId() ~= autoEquip.item1 and slotItem:getId() ~= autoEquip.item2) then
|
||||
for _, container in pairs(containers) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
if item:getId() == autoEquip.item1 or item:getId() == autoEquip.item2 then
|
||||
g_game.move(item, {x=65535, y=autoEquip.slot, z=0}, item:getCount())
|
||||
delay(1000) -- don't call it too often
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
539
modules/game_bot/default_configs/vBot_4.8/vBot/equipper.otui
Normal file
@ -0,0 +1,539 @@
|
||||
SlotBotItem < BotItem
|
||||
border-width: 0
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
$checked:
|
||||
border-width: 1
|
||||
border-color: #FF0000
|
||||
|
||||
BossLabel < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 3 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('X')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 14
|
||||
height: 14
|
||||
margin-right: 15
|
||||
text-align: center
|
||||
text-offset: 0 1
|
||||
tooltip: Remove profile from the list.
|
||||
|
||||
ConditionBoxPopupMenu < ComboBoxPopupMenu
|
||||
ConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
ConditionBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("-")
|
||||
self:addOption("and")
|
||||
self:addOption("or")
|
||||
|
||||
PreButton < PreviousButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
NexButton < NextButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
CondidionLabel < FlatPanel
|
||||
padding: 1
|
||||
height: 15
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
Rule < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 18 2
|
||||
focusable: true
|
||||
height: 16
|
||||
text-align: left
|
||||
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
|
||||
tooltip: Entry enabled/disabled
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
text: X
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
width: 14
|
||||
height: 14
|
||||
text-align: center
|
||||
tooltip: Remove entry
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Button
|
||||
id: visible
|
||||
text: V
|
||||
anchors.right: prev.left
|
||||
margin-right: 3
|
||||
width: 14
|
||||
height: 14
|
||||
text-align: center
|
||||
tooltip: Items must be visible
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
ConditionPanel < Panel
|
||||
height: 58
|
||||
|
||||
NexButton
|
||||
id: nex
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.right: parent.right
|
||||
|
||||
PreButton
|
||||
id: pre
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
|
||||
CondidionLabel
|
||||
id: description
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.left: prev.right
|
||||
anchors.right: nex.left
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
SpinBox
|
||||
id: spinbox
|
||||
anchors.top: description.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 100
|
||||
text-align: center
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
focusable: true
|
||||
|
||||
BotTextEdit
|
||||
id: text
|
||||
anchors.top: description.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 200
|
||||
text-align: center
|
||||
|
||||
|
||||
|
||||
ListPanel < FlatPanel
|
||||
size: 270 300
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Rules List
|
||||
font: verdana-11px-rounded
|
||||
color: #FABD02
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 10
|
||||
margin-left: 2
|
||||
!text: tr('More important methods come first.')
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
margin-top: 25
|
||||
margin-bottom: 18
|
||||
vertical-scrollbar: listScrollBar
|
||||
padding: 2
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: up
|
||||
anchors.right: parent.right
|
||||
anchors.top: list.bottom
|
||||
size: 60 17
|
||||
text: Move Up
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
margin-top: 5
|
||||
tooltip: Increase priority of selected rule.
|
||||
|
||||
Button
|
||||
id: down
|
||||
anchors.right: prev.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 60 17
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
tooltip: Decrease priority of selected rule.
|
||||
|
||||
InputPanel < FlatPanel
|
||||
size: 270 300
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Condition Panel
|
||||
font: verdana-11px-rounded
|
||||
color: #FF0000
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
text: Equip selected items when:
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
|
||||
ConditionPanel
|
||||
id: condition
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: mainLabel.bottom
|
||||
margin-top: 15
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
ConditionBox
|
||||
id: useSecondCondition
|
||||
anchors.top: condition.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 50
|
||||
|
||||
ConditionPanel
|
||||
id: optionalCondition
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
|
||||
BotButton
|
||||
id: add
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 10
|
||||
text: Add Rule
|
||||
|
||||
EQPanel < FlatPanel
|
||||
size: 160 230
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Equipment Setup
|
||||
font: verdana-11px-rounded
|
||||
color: #03C04A
|
||||
|
||||
SlotBotItem
|
||||
id: head
|
||||
image-source: /images/game/slots/head
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 15
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: body
|
||||
image-source: /images/game/slots/body
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: legs
|
||||
image-source: /images/game/slots/legs
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: feet
|
||||
image-source: /images/game/slots/feet
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: neck
|
||||
image-source: /images/game/slots/neck
|
||||
anchors.top: head.top
|
||||
margin-top: 13
|
||||
anchors.right: head.left
|
||||
margin-right: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: left-hand
|
||||
image-source: /images/game/slots/left-hand
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: finger
|
||||
image-source: /images/game/slots/finger
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
Item
|
||||
id: back
|
||||
image-source: /images/game/slots/back-blessed
|
||||
anchors.top: head.top
|
||||
margin-top: 13
|
||||
anchors.left: head.right
|
||||
margin-left: 5
|
||||
tooltip: Main back container modifications are unavailable.
|
||||
|
||||
SlotBotItem
|
||||
id: right-hand
|
||||
image-source: /images/game/slots/right-hand
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: ammo
|
||||
image-source: /images/game/slots/ammo
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
|
||||
BotButton
|
||||
id: cloneEq
|
||||
anchors.top: feet.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 15
|
||||
text: Clone Current EQ
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Copy currently equipped and non-equipped items.
|
||||
|
||||
BotButton
|
||||
id: default
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
text: Reset fields
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Reset all fields to the blank state
|
||||
|
||||
Profile < FlatPanel
|
||||
size: 160 35
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
text: Profile Name
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotTextEdit
|
||||
id: profileName
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin: 5
|
||||
|
||||
BossList < FlatPanel
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Boss List
|
||||
font: verdana-11px-rounded
|
||||
color: #FABD02
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
margin-top: 10
|
||||
margin-bottom: 20
|
||||
vertical-scrollbar: listScrollBar
|
||||
padding: 2
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
BotTextEdit
|
||||
id: name
|
||||
anchors.left: list.left
|
||||
anchors.top: list.bottom
|
||||
margin-top: 4
|
||||
anchors.right: next.left
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.right: list.right
|
||||
anchors.top: list.bottom
|
||||
margin-top: 3
|
||||
height: 21
|
||||
text: Add Boss
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Creature with given name will be considered as boss.
|
||||
|
||||
EquipWindow < MainWindow
|
||||
size: 750 350
|
||||
text: Equipment Manager
|
||||
@onEscape: self:hide()
|
||||
|
||||
ListPanel
|
||||
id: listPanel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-left: -2
|
||||
visible: false
|
||||
|
||||
BossList
|
||||
id: bossPanel
|
||||
anchors.fill: prev
|
||||
visible: true
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
Profile
|
||||
id: profileName
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
EQPanel
|
||||
id: setup
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-top: 10
|
||||
|
||||
InputPanel
|
||||
id: inputPanel
|
||||
anchors.left: prev.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-left: 5
|
||||
|
||||
HorizontalSeparator
|
||||
id: bottomSep
|
||||
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
|
||||
|
||||
Button
|
||||
id: bossList
|
||||
!text: tr('Boss list')
|
||||
font: cipsoftFont
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 65 21
|
27
modules/game_bot/default_configs/vBot_4.8/vBot/exeta.lua
Normal file
@ -0,0 +1,27 @@
|
||||
local voc = player:getVocation()
|
||||
if voc == 1 or voc == 11 then
|
||||
setDefaultTab("Cave")
|
||||
UI.Separator()
|
||||
local m = macro(100000, "Exeta when low hp", function() end)
|
||||
local lastCast = now
|
||||
onCreatureHealthPercentChange(function(creature, healthPercent)
|
||||
if m.isOff() then return end
|
||||
if healthPercent > 15 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
|
||||
say("exeta res")
|
||||
lastCast = now
|
||||
end
|
||||
end)
|
||||
|
||||
macro(500, "ExetaIfPlayer", function()
|
||||
if CaveBot.isOff() then return end
|
||||
if getMonsters(1) >= 1 and getPlayers(6) > 0 then
|
||||
say("exeta res")
|
||||
delay(6000)
|
||||
end
|
||||
end)
|
||||
UI.Separator()
|
||||
end
|
644
modules/game_bot/default_configs/vBot_4.8/vBot/extras.lua
Normal file
@ -0,0 +1,644 @@
|
||||
setDefaultTab("Main")
|
||||
|
||||
-- securing storage namespace
|
||||
local panelName = "extras"
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {}
|
||||
end
|
||||
local settings = storage[panelName]
|
||||
|
||||
-- basic elements
|
||||
extrasWindow = UI.createWindow('ExtrasWindow', rootWidget)
|
||||
extrasWindow:hide()
|
||||
extrasWindow.closeButton.onClick = function(widget)
|
||||
extrasWindow:hide()
|
||||
end
|
||||
|
||||
extrasWindow.onGeometryChange = function(widget, old, new)
|
||||
if old.height == 0 then return end
|
||||
|
||||
settings.height = new.height
|
||||
end
|
||||
|
||||
extrasWindow:setHeight(settings.height or 360)
|
||||
|
||||
-- available options for dest param
|
||||
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, 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
|
||||
widget:setOn(settings[id])
|
||||
end
|
||||
settings[id] = widget:isOn()
|
||||
end
|
||||
|
||||
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()
|
||||
end
|
||||
settings[id] = settings[id] or defaultItem
|
||||
end
|
||||
|
||||
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, 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
|
||||
value = 1
|
||||
end
|
||||
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
|
||||
widget.scroll:setStep(10)
|
||||
end
|
||||
widget.scroll:setValue(settings[id] or defaultValue)
|
||||
widget.scroll.onValueChange(widget.scroll, widget.scroll:getValue())
|
||||
end
|
||||
|
||||
UI.Button("vBot Settings and Scripts", function()
|
||||
extrasWindow:show()
|
||||
extrasWindow:raise()
|
||||
extrasWindow:focus()
|
||||
end)
|
||||
UI.Separator()
|
||||
|
||||
---- to maintain order, add options right after another:
|
||||
--- add object
|
||||
--- add variables for function (optional)
|
||||
--- add callback (optional)
|
||||
--- optionals should be addionaly sandboxed (if true then end)
|
||||
|
||||
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.")
|
||||
addCheckBox("pathfinding", "CaveBot Pathfinding", true, leftPanel, "Cavebot will automatically search for first reachable waypoint after missing 10 goto's.")
|
||||
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("lootDelay", "Loot Delay", 0, 1000, 200, leftPanel, "Wait time for loot container to open. Lower value means faster looting. \n WARNING if you are having looting issues(e.g. container is locked in closing/opnening), increase this value.")
|
||||
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, "Personalize OTCv8 window name according to character specific.")
|
||||
if true then
|
||||
local vocText = ""
|
||||
|
||||
if voc() == 1 or voc() == 11 then
|
||||
vocText = "- EK"
|
||||
elseif voc() == 2 or voc() == 12 then
|
||||
vocText = "- RP"
|
||||
elseif voc() == 3 or voc() == 13 then
|
||||
vocText = "- MS"
|
||||
elseif voc() == 4 or voc() == 14 then
|
||||
vocText = "- ED"
|
||||
end
|
||||
|
||||
macro(5000, function()
|
||||
if settings.title then
|
||||
if hppercent() > 0 then
|
||||
g_window.setTitle("Tibia - " .. name() .. " - " .. lvl() .. "lvl " .. vocText)
|
||||
else
|
||||
g_window.setTitle("Tibia - " .. name() .. " - DEAD")
|
||||
end
|
||||
else
|
||||
g_window.setTitle("Tibia - " .. name())
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
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
|
||||
local g_console = modules.game_console
|
||||
local privateTab = g_console.getTab(name)
|
||||
if privateTab == nil then
|
||||
privateTab = g_console.addTab(name, true)
|
||||
g_console.addPrivateText(g_console.applyMessagePrefixies(name, level, text), g_console.SpeakTypesSettings['private'], name, false, name)
|
||||
end
|
||||
return
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addTextEdit("useAll", "Use All Hotkey", "space", rightPanel, "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,
|
||||
1629, 1630, 5108, 5107, 5281, 1968, 435, 1948, 5542, 31116, 31120, 30742, 31115,
|
||||
31118, 20474, 5737, 5736, 5734, 5733, 31202, 31228, 31199, 31200, 33262, 30824,
|
||||
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, 608 }
|
||||
local ropeId = { 17238, 12202, 12935, 386, 421, 21966, 14238 }
|
||||
local macheteId = { 2130, 3696 }
|
||||
local scytheId = { 3653 }
|
||||
|
||||
setDefaultTab("Tools")
|
||||
-- script
|
||||
if settings.useAll and settings.useAll:len() > 0 then
|
||||
hotkey(settings.useAll, function()
|
||||
if not modules.game_walking.wsadWalking then return end
|
||||
for _, tile in pairs(g_map.getTiles(posz())) do
|
||||
if distanceFromPlayer(tile:getPosition()) < 2 then
|
||||
for _, item in pairs(tile:getItems()) do
|
||||
-- use
|
||||
if table.find(useId, item:getId()) then
|
||||
use(item)
|
||||
return
|
||||
elseif table.find(shovelId, item:getId()) then
|
||||
useWith(settings.shovel, item)
|
||||
return
|
||||
elseif table.find(ropeId, item:getId()) then
|
||||
useWith(settings.rope, item)
|
||||
return
|
||||
elseif table.find(macheteId, item:getId()) then
|
||||
useWith(settings.machete, item)
|
||||
return
|
||||
elseif table.find(scytheId, item:getId()) then
|
||||
useWith(settings.scythe, item)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("timers", "MW & WG Timers", true, rightPanel, "Show times for Magic Walls and Wild Growths.")
|
||||
if true then
|
||||
local activeTimers = {}
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if not settings.timers then return end
|
||||
if not thing:isItem() then
|
||||
return
|
||||
end
|
||||
local timer = 0
|
||||
if thing:getId() == 2129 then -- mwall id
|
||||
timer = 20000 -- mwall time
|
||||
elseif thing:getId() == 2130 then -- wg id
|
||||
timer = 45000 -- wg time
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not activeTimers[pos] or activeTimers[pos] < now then
|
||||
activeTimers[pos] = now + timer
|
||||
end
|
||||
tile:setTimer(activeTimers[pos] - now)
|
||||
end)
|
||||
|
||||
onRemoveThing(function(tile, thing)
|
||||
if not settings.timers then return end
|
||||
if not thing:isItem() then
|
||||
return
|
||||
end
|
||||
if (thing:getId() == 2129 or thing:getId() == 2130) and tile:getGround() then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
activeTimers[pos] = nil
|
||||
tile:setTimer(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
local dir = player:getDirection()
|
||||
turn((dir + 1) % 4)
|
||||
schedule(50, function() turn(dir) end)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
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}
|
||||
local fishingBodies = {9582}
|
||||
macro(500, function()
|
||||
if not CaveBot.isOn() or not settings.stake then return end
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) 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)
|
||||
return
|
||||
end
|
||||
if table.find(stakeBodies, item:getId()) and findItem(5942) then
|
||||
CaveBot.delay(550)
|
||||
useWith(5942, item)
|
||||
return
|
||||
end
|
||||
if table.find(fishingBodies, item:getId()) and findItem(3483) then
|
||||
CaveBot.delay(550)
|
||||
useWith(3483, item)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
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?")
|
||||
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
|
||||
say("Too bad you barely exist at all!")
|
||||
elseif string.find(text, "ESDO LO") then
|
||||
say("SEHWO ASIMO, TOLIDO ESD")
|
||||
elseif string.find(text, "will soon rule this world") then
|
||||
say("Excuse me but I still do not get the message!")
|
||||
elseif string.find(text, "honourable and formidable") then
|
||||
say("Then why are we fighting alone right now?")
|
||||
elseif string.find(text, "appear like a worm") then
|
||||
say("How appropriate, you look like something worms already got the better of!")
|
||||
elseif string.find(text, "will be the end of mortal") then
|
||||
say("Then let me show you the concept of mortality before it!")
|
||||
elseif string.find(text, "virtues of chivalry") then
|
||||
say("Dare strike up a Minnesang and you will receive your last accolade!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("autoOpenDoors", "Auto Open Doors", true, rightPanel, "Open doors when trying to step on them.")
|
||||
if true then
|
||||
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,
|
||||
1632, 11705, 30772, 30774, 6248, 5735, 5732, 5120, 23873, 5736,
|
||||
6264, 5122, 30049, 30042, 7727 }
|
||||
|
||||
function checkForDoors(pos)
|
||||
local tile = g_map.getTile(pos)
|
||||
if tile then
|
||||
local useThing = tile:getTopUseThing()
|
||||
if useThing and table.find(doorsIds, useThing:getId()) then
|
||||
g_game.use(useThing)
|
||||
end
|
||||
end
|
||||
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
|
||||
pos.y = pos.y - 1
|
||||
elseif keys == 'Down' or (wsadWalking and keys == 'S') then
|
||||
pos.y = pos.y + 1
|
||||
elseif keys == 'Left' or (wsadWalking and keys == 'A') then
|
||||
pos.x = pos.x - 1
|
||||
elseif keys == 'Right' or (wsadWalking and keys == 'D') then
|
||||
pos.x = pos.x + 1
|
||||
elseif wsadWalking and keys == "Q" then
|
||||
pos.y = pos.y - 1
|
||||
pos.x = pos.x - 1
|
||||
elseif wsadWalking and keys == "E" then
|
||||
pos.y = pos.y - 1
|
||||
pos.x = pos.x + 1
|
||||
elseif wsadWalking and keys == "Z" then
|
||||
pos.y = pos.y + 1
|
||||
pos.x = pos.x - 1
|
||||
elseif wsadWalking and keys == "C" then
|
||||
pos.y = pos.y + 1
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
checkForDoors(pos)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("bless", "Buy bless at login", true, rightPanel, "Say !bless at login.")
|
||||
if true then
|
||||
local blessed = false
|
||||
onTextMessage(function(mode,text)
|
||||
if not settings.bless then return end
|
||||
|
||||
text = text:lower()
|
||||
|
||||
if text == "you already have all blessings." then
|
||||
blessed = true
|
||||
end
|
||||
end)
|
||||
if settings.bless then
|
||||
if player:getBlessings() == 0 then
|
||||
say("!bless")
|
||||
schedule(2000, function()
|
||||
if g_game.getClientVersion() > 1000 then
|
||||
if not blessed and player:getBlessings() == 0 then
|
||||
warn("!! Blessings not bought !!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
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}
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if settings.reUse and not table.find(excluded, itemId) then
|
||||
schedule(50, function()
|
||||
item = findItem(itemId)
|
||||
if item then
|
||||
modules.game_interface.startUseWith(item)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
if TargetBot.isOff() then return end
|
||||
if CaveBot.isOff() then return end
|
||||
if type(hasSupplies()) == 'table' then
|
||||
TargetBot.setOff()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
local hold = 0
|
||||
local mwHot
|
||||
local wgHot
|
||||
|
||||
local candidates = {}
|
||||
local m = macro(20, function()
|
||||
mwHot = settings.holdMwHot
|
||||
wgHot = settings.holdWgHot
|
||||
|
||||
if not settings.holdMwall then return end
|
||||
if #candidates == 0 then return end
|
||||
|
||||
for i, pos in pairs(candidates) do
|
||||
local tile = g_map.getTile(pos)
|
||||
if tile then
|
||||
if tile:getText():len() == 0 then
|
||||
table.remove(candidates, i)
|
||||
end
|
||||
local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
|
||||
if tile:canShoot() and not isInPz() and tile:isWalkable() and tile:getTopUseThing():getId() ~= 2130 then
|
||||
if math.abs(player:getPosition().x-tile:getPosition().x) < 8 and math.abs(player:getPosition().y-tile:getPosition().y) < 6 then
|
||||
return useWith(rune, tile:getTopUseThing())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onRemoveThing(function(tile, thing)
|
||||
if not settings.holdMwall then return end
|
||||
if thing:getId() ~= 2129 then return end
|
||||
if tile:getText():find("HOLD") then
|
||||
table.insert(candidates, tile:getPosition())
|
||||
local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
|
||||
if math.abs(player:getPosition().x-tile:getPosition().x) < 8 and math.abs(player:getPosition().y-tile:getPosition().y) < 6 then
|
||||
return useWith(rune, tile:getTopUseThing())
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if thing:getId() ~= 2129 then return end
|
||||
if tile:getText():len() > 0 then
|
||||
table.remove(candidates, table.find(candidates,tile))
|
||||
end
|
||||
end)
|
||||
|
||||
onKeyDown(function(keys)
|
||||
local wsadWalking = modules.game_walking.wsadWalking
|
||||
if not wsadWalking then return end
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if keys ~= mwHot and keys ~= wgHot then return end
|
||||
hold = now
|
||||
|
||||
local tile = getTileUnderCursor()
|
||||
if not tile then return end
|
||||
|
||||
if tile:getText():len() > 0 then
|
||||
tile:setText("")
|
||||
else
|
||||
if keys == mwHot then
|
||||
tile:setText("HOLD MW")
|
||||
else
|
||||
tile:setText("HOLD WG")
|
||||
end
|
||||
table.insert(candidates, tile:getPosition())
|
||||
end
|
||||
end)
|
||||
|
||||
onKeyPress(function(keys)
|
||||
local wsadWalking = modules.game_walking.wsadWalking
|
||||
if not wsadWalking then return end
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if keys ~= mwHot and keys ~= wgHot then return end
|
||||
|
||||
if (hold - now) < -1000 then
|
||||
candidates = {}
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local text = tile:getText()
|
||||
if text:find("HOLD") then
|
||||
tile:setText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
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()
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec:getText() == "" and spec:getPosition().z == posz() and spec ~= player then
|
||||
g_game.look(spec)
|
||||
found = now
|
||||
end
|
||||
end
|
||||
end
|
||||
if settings.checkPlayer then
|
||||
schedule(500, function()
|
||||
checkPlayers()
|
||||
end)
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(x,y)
|
||||
if not settings.checkPlayer then return end
|
||||
if x.z ~= y.z then
|
||||
schedule(20, function() checkPlayers() end)
|
||||
end
|
||||
end)
|
||||
|
||||
onCreatureAppear(function(creature)
|
||||
if not settings.checkPlayer then return end
|
||||
if creature:isPlayer() and creature:getText() == "" and creature:getPosition().z == posz() and creature ~= player then
|
||||
g_game.look(creature)
|
||||
found = now
|
||||
end
|
||||
end)
|
||||
|
||||
local regex = [[You see ([^\(]*) \(Level ([0-9]*)\)((?:.)* of the ([\w ]*),|)]]
|
||||
onTextMessage(function(mode, text)
|
||||
if not settings.checkPlayer then return end
|
||||
|
||||
local re = regexMatch(text, regex)
|
||||
if #re ~= 0 then
|
||||
local name = re[1][2]
|
||||
local level = re[1][3]
|
||||
local guild = re[1][5] or ""
|
||||
|
||||
if guild:len() > 10 then
|
||||
guild = guild:sub(1,10) -- change to proper (last) values
|
||||
guild = guild.."..."
|
||||
end
|
||||
local voc
|
||||
if text:lower():find("sorcerer") then
|
||||
voc = "MS"
|
||||
elseif text:lower():find("druid") then
|
||||
voc = "ED"
|
||||
elseif text:lower():find("knight") then
|
||||
voc = "EK"
|
||||
elseif text:lower():find("paladin") then
|
||||
voc = "RP"
|
||||
end
|
||||
local creature = getCreatureByName(name)
|
||||
if creature then
|
||||
creature:setText("\n"..level..voc.."\n"..guild)
|
||||
end
|
||||
if found and now - found < 500 then
|
||||
modules.game_textmessage.clearMessages()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
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()
|
||||
|
||||
for i, container in ipairs(containers) do
|
||||
local cId = container:getContainerItem():getId()
|
||||
if containerIsFull(container) then
|
||||
if table.find(lootCotaniersIds, cId) then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:getId() == cId then
|
||||
return g_game.open(item, container)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if true then
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
schedule(100, function()
|
||||
openNextLootContainer()
|
||||
end)
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
schedule(100, function()
|
||||
openNextLootContainer()
|
||||
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
|
158
modules/game_bot/default_configs/vBot_4.8/vBot/extras.otui
Normal file
@ -0,0 +1,158 @@
|
||||
ExtrasScrollBar < Panel
|
||||
height: 28
|
||||
margin-top: 3
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
ExtrasTextEdit < Panel
|
||||
height: 40
|
||||
margin-top: 7
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
TextEdit
|
||||
id: textEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
text-align: center
|
||||
|
||||
ExtrasItem < Panel
|
||||
height: 34
|
||||
margin-top: 7
|
||||
margin-left: 25
|
||||
margin-right: 25
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
ExtrasCheckBox < BotSwitch
|
||||
height: 20
|
||||
margin-top: 7
|
||||
|
||||
ExtrasWindow < MainWindow
|
||||
!text: tr('Extras')
|
||||
size: 440 360
|
||||
padding: 25
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: < CaveBot >
|
||||
|
||||
Label
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: < Miscellaneous >
|
||||
|
||||
VerticalScrollBar
|
||||
id: contentScroll
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: separator.top
|
||||
step: 28
|
||||
pixels-scroll: true
|
||||
margin-right: -10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
ScrollablePanel
|
||||
id: content
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: separator.top
|
||||
vertical-scrollbar: contentScroll
|
||||
margin-bottom: 10
|
||||
|
||||
Panel
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
ResizeBorder
|
||||
id: bottomResizeBorder
|
||||
anchors.fill: separator
|
||||
height: 3
|
||||
minimum: 260
|
||||
maximum: 600
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
background: #ffffff88
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-right: 5
|
@ -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)
|
@ -0,0 +1,23 @@
|
||||
setDefaultTab("Tools")
|
||||
-- allows to test/edit bot lua scripts ingame, you can have multiple scripts like this, just change storage.ingame_lua
|
||||
UI.Button("Ingame script editor", function(newText)
|
||||
UI.MultilineEditorWindow(storage.ingame_hotkeys or "", {title="Hotkeys editor", description="You can add your custom scrupts here"}, function(text)
|
||||
storage.ingame_hotkeys = text
|
||||
reload()
|
||||
end)
|
||||
end)
|
||||
|
||||
UI.Separator()
|
||||
|
||||
for _, scripts in pairs({storage.ingame_hotkeys}) do
|
||||
if type(scripts) == "string" and scripts:len() > 3 then
|
||||
local status, result = pcall(function()
|
||||
assert(load(scripts, "ingame_editor"))()
|
||||
end)
|
||||
if not status then
|
||||
error("Ingame edior error:\n" .. result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
UI.Separator()
|
1404
modules/game_bot/default_configs/vBot_4.8/vBot/items.lua
Normal file
40
modules/game_bot/default_configs/vBot_4.8/vBot/main.lua
Normal file
@ -0,0 +1,40 @@
|
||||
local version = "4.8"
|
||||
local currentVersion
|
||||
local available = false
|
||||
|
||||
storage.checkVersion = storage.checkVersion or 0
|
||||
|
||||
-- check max once per 12hours
|
||||
if os.time() > storage.checkVersion + (12 * 60 * 60) then
|
||||
|
||||
storage.checkVersion = os.time()
|
||||
|
||||
HTTP.get("https://raw.githubusercontent.com/Vithrax/vBot/main/vBot/version.txt", function(data, err)
|
||||
if err then
|
||||
warn("[vBot updater]: Unable to check version:\n" .. err)
|
||||
return
|
||||
end
|
||||
|
||||
currentVersion = data
|
||||
available = true
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
UI.Label("vBot v".. version .." \n Vithrax#5814")
|
||||
UI.Button("Official OTCv8 Discord!", function() g_platform.openUrl("https://discord.gg/yhqBE4A") end)
|
||||
UI.Separator()
|
||||
|
||||
schedule(5000, function()
|
||||
|
||||
if not available then return end
|
||||
if currentVersion ~= version then
|
||||
|
||||
UI.Separator()
|
||||
UI.Label("New vBot is available for download! v"..currentVersion)
|
||||
UI.Button("Go to vBot GitHub Page", function() g_platform.openUrl("https://github.com/Vithrax/vBot") end)
|
||||
UI.Separator()
|
||||
|
||||
end
|
||||
|
||||
end)
|
@ -0,0 +1,518 @@
|
||||
CaveBot = {} -- global namespace
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- CaveBot lib 1.0
|
||||
-- Contains a universal set of functions to be used in CaveBot
|
||||
|
||||
----------------------[[ basic assumption ]]-----------------------
|
||||
-- in general, functions cannot be slowed from within, only externally, by event calls, delays etc.
|
||||
-- considering that and the fact that there is no while loop, every function return action
|
||||
-- thus, functions will need to be verified outside themselfs or by another function
|
||||
-- overall tips to creating extension:
|
||||
-- - functions return action(nil) or true(done)
|
||||
-- - extensions are controlled by retries var
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- local variables, constants and functions, used by global functions
|
||||
local LOCKERS_LIST = {3497, 3498, 3499, 3500}
|
||||
local LOCKER_ACCESSTILE_MODIFIERS = {
|
||||
[3497] = {0,-1},
|
||||
[3498] = {1,0},
|
||||
[3499] = {0,1},
|
||||
[3500] = {-1,0}
|
||||
}
|
||||
|
||||
local function CaveBotConfigParse()
|
||||
local name = storage["_configs"]["targetbot_configs"]["selected"]
|
||||
if not name then
|
||||
return warn("[vBot] Please create a new TargetBot config and reset bot")
|
||||
end
|
||||
local file = configDir .. "/targetbot_configs/" .. name .. ".json"
|
||||
local data = g_resources.readFileContents(file)
|
||||
return Config.parse(data)['looting']
|
||||
end
|
||||
|
||||
local function getNearTiles(pos)
|
||||
if type(pos) ~= "table" then
|
||||
pos = pos:getPosition()
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
local dirs = {
|
||||
{-1, 1},
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{-1, 0},
|
||||
{1, 0},
|
||||
{-1, -1},
|
||||
{0, -1},
|
||||
{1, -1}
|
||||
}
|
||||
for i = 1, #dirs do
|
||||
local tile =
|
||||
g_map.getTile(
|
||||
{
|
||||
x = pos.x - dirs[i][1],
|
||||
y = pos.y - dirs[i][2],
|
||||
z = pos.z
|
||||
}
|
||||
)
|
||||
if tile then
|
||||
table.insert(tiles, tile)
|
||||
end
|
||||
end
|
||||
|
||||
return tiles
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[ Information class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- global variable to reflect current CaveBot status
|
||||
CaveBot.Status = "waiting"
|
||||
|
||||
--- Parses config and extracts loot list.
|
||||
-- @return table
|
||||
function CaveBot.GetLootItems()
|
||||
local t = CaveBotConfigParse() and CaveBotConfigParse()["items"] or nil
|
||||
|
||||
local returnTable = {}
|
||||
if type(t) == "table" then
|
||||
for i, item in pairs(t) do
|
||||
table.insert(returnTable, item["id"])
|
||||
end
|
||||
end
|
||||
|
||||
return returnTable
|
||||
end
|
||||
|
||||
|
||||
--- Checks whether player has any visible items to be stashed
|
||||
-- @return boolean
|
||||
function CaveBot.HasLootItems()
|
||||
for _, container in pairs(getContainers()) do
|
||||
local name = container:getName():lower()
|
||||
if not name:find("depot") and not name:find("your inbox") then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(CaveBot.GetLootItems(), id) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Parses config and extracts loot containers.
|
||||
-- @return table
|
||||
function CaveBot.GetLootContainers()
|
||||
local t = CaveBotConfigParse() and CaveBotConfigParse()["containers"] or nil
|
||||
|
||||
local returnTable = {}
|
||||
if type(t) == "table" then
|
||||
for i, container in pairs(t) do
|
||||
table.insert(returnTable, container["id"])
|
||||
end
|
||||
end
|
||||
|
||||
return returnTable
|
||||
end
|
||||
|
||||
--- Information about open containers.
|
||||
-- @param amount is boolean
|
||||
-- @return table or integer
|
||||
function CaveBot.GetOpenedLootContainers(containerTable)
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
local t = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
table.insert(t, container)
|
||||
end
|
||||
end
|
||||
|
||||
return containerTable and t or #t
|
||||
end
|
||||
|
||||
--- Some actions needs to be additionally slowed down in case of high ping.
|
||||
-- Maximum at 2000ms in case of lag spike.
|
||||
-- @param multiplayer is integer
|
||||
-- @return void
|
||||
function CaveBot.PingDelay(multiplayer)
|
||||
multiplayer = multiplayer or 1
|
||||
if ping() and ping() > 150 then -- in most cases ping above 150 affects CaveBot
|
||||
local value = math.min(ping() * multiplayer, 2000)
|
||||
return delay(value)
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[ Container class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Closes any loot container that is open.
|
||||
-- @return void or boolean
|
||||
function CaveBot.CloseLootContainer()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
return g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function CaveBot.CloseAllLootContainers()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Opens any loot container that isn't already opened.
|
||||
-- @return void or boolean
|
||||
function CaveBot.OpenLootContainer()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
local t = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
table.insert(t, containerId)
|
||||
end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(containers, id) and not table.find(t, id) then
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[ Position class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Compares distance between player position and given pos.
|
||||
-- @param position is table
|
||||
-- @param distance is integer
|
||||
-- @return boolean
|
||||
function CaveBot.MatchPosition(position, distance)
|
||||
local pPos = player:getPosition()
|
||||
distance = distance or 1
|
||||
return getDistanceBetween(pPos, position) <= distance
|
||||
end
|
||||
|
||||
--- Stripped down to take less space.
|
||||
-- Use only to safe position, like pz movement or reaching npc.
|
||||
-- Needs to be called between 200-500ms to achieve fluid movement.
|
||||
-- @param position is table
|
||||
-- @param distance is integer
|
||||
-- @return void
|
||||
function CaveBot.GoTo(position, precision)
|
||||
if not precision then
|
||||
precision = 3
|
||||
end
|
||||
return CaveBot.walkTo(position, 20, {ignoreCreatures = true, precision = precision})
|
||||
end
|
||||
|
||||
--- Finds position of npc by name and reaches its position.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.ReachNPC(name)
|
||||
name = name:lower()
|
||||
|
||||
local npc = nil
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isNpc() and spec:getName():lower() == name then
|
||||
npc = spec
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.MatchPosition(npc:getPosition(), 3) then
|
||||
CaveBot.GoTo(npc:getPosition())
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[[ Depot class ]]]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Reaches closest locker.
|
||||
-- @return void(acion) or boolean
|
||||
|
||||
local depositerLockerTarget = nil
|
||||
local depositerLockerReachRetries = 0
|
||||
function CaveBot.ReachDepot()
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(player:getPosition())
|
||||
|
||||
for i, tile in pairs(tiles) do
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
depositerLockerTarget = nil
|
||||
depositerLockerReachRetries = 0
|
||||
return true -- if near locker already then return function
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if depositerLockerReachRetries > 20 then
|
||||
depositerLockerTarget = nil
|
||||
depositerLockerReachRetries = 0
|
||||
end
|
||||
|
||||
local candidates = {}
|
||||
|
||||
if not depositerLockerTarget or distanceFromPlayer(depositerLockerTarget, pPos) > 12 then
|
||||
for i, tile in pairs(g_map.getTiles(posz())) do
|
||||
local tPos = tile:getPosition()
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
local lockerTilePos = tile:getPosition()
|
||||
lockerTilePos.x = lockerTilePos.x + LOCKER_ACCESSTILE_MODIFIERS[item:getId()][1]
|
||||
lockerTilePos.y = lockerTilePos.y + LOCKER_ACCESSTILE_MODIFIERS[item:getId()][2]
|
||||
local lockerTile = g_map.getTile(lockerTilePos)
|
||||
if not lockerTile:hasCreature() then
|
||||
if findPath(pos(), tPos, 20, {ignoreNonPathable = false, precision = 1, ignoreCreatures = true}) then
|
||||
local distance = getDistanceBetween(tPos, pPos)
|
||||
table.insert(candidates, {pos=tPos, dist=distance})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #candidates > 1 then
|
||||
table.sort(candidates, function(a,b) return a.dist < b.dist end)
|
||||
end
|
||||
end
|
||||
|
||||
depositerLockerTarget = depositerLockerTarget or candidates[1].pos
|
||||
|
||||
if depositerLockerTarget then
|
||||
if not CaveBot.MatchPosition(depositerLockerTarget) then
|
||||
depositerLockerReachRetries = depositerLockerReachRetries + 1
|
||||
return CaveBot.GoTo(depositerLockerTarget, 1)
|
||||
else
|
||||
depositerLockerReachRetries = 0
|
||||
depositerLockerTarget = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens locker item.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenLocker()
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(player:getPosition())
|
||||
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
for i, tile in pairs(tiles) do
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing:isNotMoveable() then
|
||||
g_game.move(topThing, pPos, topThing:getCount())
|
||||
else
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens depot chest.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenDepotChest()
|
||||
local depot = getContainerByName("Depot chest")
|
||||
if not depot then
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
return CaveBot.OpenLocker()
|
||||
end
|
||||
for i, item in pairs(locker:getItems()) do
|
||||
if item:getId() == 3502 then
|
||||
return g_game.open(item, locker)
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens inbox inside locker.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenInbox()
|
||||
local inbox = getContainerByName("Your inbox")
|
||||
if not inbox then
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
return CaveBot.OpenLocker()
|
||||
end
|
||||
for i, item in pairs(locker:getItems()) do
|
||||
if item:getId() == 12902 then
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens depot box of given number.
|
||||
-- @param index is integer
|
||||
-- @return void or boolean
|
||||
function CaveBot.OpenDepotBox(index)
|
||||
local depot = getContainerByName("Depot chest")
|
||||
if not depot then
|
||||
return CaveBot.ReachAndOpenDepot()
|
||||
end
|
||||
|
||||
local foundParent = false
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower():find("depot box") then
|
||||
foundParent = container
|
||||
break
|
||||
end
|
||||
end
|
||||
if foundParent then return true end
|
||||
|
||||
for i, container in pairs(depot:getItems()) do
|
||||
if i == index then
|
||||
return g_game.open(container)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Reaches and opens depot.
|
||||
-- Combined for shorthand usage.
|
||||
-- @return boolean whether succeed to reach and open depot
|
||||
function CaveBot.ReachAndOpenDepot()
|
||||
if CaveBot.ReachDepot() and CaveBot.OpenDepotChest() then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Reaches and opens imbox.
|
||||
-- Combined for shorthand usage.
|
||||
-- @return boolean whether succeed to reach and open depot
|
||||
function CaveBot.ReachAndOpenInbox()
|
||||
if CaveBot.ReachDepot() and CaveBot.OpenInbox() then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Stripped down function to stash item.
|
||||
-- @param item is object
|
||||
-- @param index is integer
|
||||
-- @param destination is object
|
||||
-- @return void
|
||||
function CaveBot.StashItem(item, index, destination)
|
||||
destination = destination or getContainerByName("Depot chest")
|
||||
if not destination then return false end
|
||||
|
||||
return g_game.move(item, destination:getSlotPosition(index), item:getCount())
|
||||
end
|
||||
|
||||
--- Withdraws item from depot chest or mail inbox.
|
||||
-- main function for depositer/withdrawer
|
||||
-- @param id is integer
|
||||
-- @param amount is integer
|
||||
-- @param fromDepot is boolean or integer
|
||||
-- @param destination is object
|
||||
-- @return void
|
||||
function CaveBot.WithdrawItem(id, amount, fromDepot, destination)
|
||||
if destination and type(destination) == "string" then
|
||||
destination = getContainerByName(destination)
|
||||
end
|
||||
local itemCount = itemAmount(id)
|
||||
local depot
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower():find("depot box") or container:getName():lower():find("your inbox") then
|
||||
depot = container
|
||||
break
|
||||
end
|
||||
end
|
||||
if not depot then
|
||||
if fromDepot then
|
||||
if not CaveBot.OpenDepotBox(fromDepot) then return end
|
||||
else
|
||||
return CaveBot.ReachAndOpenInbox()
|
||||
end
|
||||
return
|
||||
end
|
||||
if not destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "quiver") and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount >= amount then
|
||||
return true
|
||||
end
|
||||
|
||||
local toMove = amount - itemCount
|
||||
for i, item in pairs(depot:getItems()) do
|
||||
if item:getId() == id then
|
||||
return g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(toMove, item:getCount()))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[[[ Talk class ]]]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Controlled by event caller.
|
||||
-- Simple way to build npc conversations instead of multiline overcopied code.
|
||||
-- @return void
|
||||
function CaveBot.Conversation(...)
|
||||
local expressions = {...}
|
||||
local delay = storage.extras.talkDelay or 1000
|
||||
|
||||
local talkDelay = 0
|
||||
for i, expr in ipairs(expressions) do
|
||||
schedule(talkDelay, function() NPC.say(expr) end)
|
||||
talkDelay = talkDelay + delay
|
||||
end
|
||||
end
|
||||
|
||||
--- Says hi trade to NPC.
|
||||
-- Used as shorthand to open NPC trade window.
|
||||
-- @return void
|
||||
function CaveBot.OpenNpcTrade()
|
||||
return CaveBot.Conversation("hi", "trade")
|
||||
end
|
||||
|
||||
--- Says hi destination yes to NPC.
|
||||
-- Used as shorthand to travel.
|
||||
-- @param destination is string
|
||||
-- @return void
|
||||
function CaveBot.Travel(destination)
|
||||
return CaveBot.Conversation("hi", destination, "yes")
|
||||
end
|
456
modules/game_bot/default_configs/vBot_4.8/vBot/new_healer.lua
Normal file
@ -0,0 +1,456 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "newHealer"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Friend Healer')
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
-- validate current settings
|
||||
if not storage[panelName] or not storage[panelName].priorities then
|
||||
storage[panelName] = nil
|
||||
end
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
customPlayers = {},
|
||||
vocations = {},
|
||||
groups = {},
|
||||
priorities = {
|
||||
|
||||
{name="Custom Spell", enabled=false, custom=true},
|
||||
{name="Exura Gran Sio", enabled=true, strong = true},
|
||||
{name="Exura Sio", enabled=true, normal = true},
|
||||
{name="Exura Gran Mas Res", enabled=true, area = true},
|
||||
{name="Health Item", enabled=true, health=true},
|
||||
{name="Mana Item", enabled=true, mana=true}
|
||||
|
||||
},
|
||||
settings = {
|
||||
|
||||
{type="HealItem", text="Mana Item ", value=268},
|
||||
{type="HealScroll", text="Item Range: ", value=6},
|
||||
{type="HealItem", text="Health Item ", value=3160},
|
||||
{type="HealScroll", text="Mas Res Players: ", value=2},
|
||||
{type="HealScroll", text="Heal Friend at: ", value=80},
|
||||
{type="HealScroll", text="Use Gran Sio at: ", value=80},
|
||||
{type="HealScroll", text="Min Player HP%: ", value=80},
|
||||
{type="HealScroll", text="Min Player MP%: ", value=50},
|
||||
|
||||
},
|
||||
conditions = {
|
||||
knights = true,
|
||||
paladins = true,
|
||||
druids = false,
|
||||
sorcerers = false,
|
||||
party = true,
|
||||
guild = false,
|
||||
botserver = false,
|
||||
friends = false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
local healerWindow = UI.createWindow('FriendHealer')
|
||||
healerWindow:hide()
|
||||
healerWindow:setId(panelName)
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
ui.edit.onClick = function()
|
||||
healerWindow:show()
|
||||
healerWindow:raise()
|
||||
healerWindow:focus()
|
||||
end
|
||||
|
||||
local conditions = healerWindow.conditions
|
||||
local targetSettings = healerWindow.targetSettings
|
||||
local customList = healerWindow.customList
|
||||
local priority = healerWindow.priority
|
||||
|
||||
-- customList
|
||||
-- create entries on the list
|
||||
for name, health in pairs(config.customPlayers) do
|
||||
local widget = UI.createWidget("HealerPlayerEntry", customList.playerList.list)
|
||||
widget.remove.onClick = function()
|
||||
config.customPlayers[name] = nil
|
||||
widget:destroy()
|
||||
end
|
||||
widget:setText("["..health.."%] "..name)
|
||||
end
|
||||
|
||||
customList.playerList.onDoubleClick = function()
|
||||
customList.playerList:hide()
|
||||
end
|
||||
|
||||
local function clearFields()
|
||||
customList.addPanel.name:setText("friend name")
|
||||
customList.addPanel.health:setText("1")
|
||||
customList.playerList:show()
|
||||
end
|
||||
|
||||
local function capitalFistLetter(str)
|
||||
return (string.gsub(str, "^%l", string.upper))
|
||||
end
|
||||
|
||||
customList.addPanel.add.onClick = function()
|
||||
local name = ""
|
||||
local words = string.split(customList.addPanel.name:getText(), " ")
|
||||
local health = tonumber(customList.addPanel.health:getText())
|
||||
for i, word in ipairs(words) do
|
||||
name = name .. " " .. capitalFistLetter(word)
|
||||
end
|
||||
|
||||
if not health then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Please enter health percent value!")
|
||||
end
|
||||
|
||||
if name:len() == 0 or name:lower() == "friend name" then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Please enter friend name to be added!")
|
||||
end
|
||||
|
||||
if config.customPlayers[name] or config.customPlayers[name:lower()] then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Player already added to custom list.")
|
||||
else
|
||||
config.customPlayers[name] = health
|
||||
local widget = UI.createWidget("HealerPlayerEntry", customList.playerList.list)
|
||||
widget.remove.onClick = function()
|
||||
config.customPlayers[name] = nil
|
||||
widget:destroy()
|
||||
end
|
||||
widget:setText("["..health.."%] "..name)
|
||||
end
|
||||
|
||||
clearFields()
|
||||
end
|
||||
|
||||
local function validate(widget, category)
|
||||
local list = widget:getParent()
|
||||
local label = list:getParent().title
|
||||
-- 1 - priorities | 2 - vocation
|
||||
category = category or 0
|
||||
|
||||
if category == 2 and not storage.extras.checkPlayer then
|
||||
label:setColor("#d9321f")
|
||||
label:setTooltip("! WARNING ! \nTurn on check players in extras to use this feature!")
|
||||
return
|
||||
else
|
||||
label:setColor("#dfdfdf")
|
||||
label:setTooltip("")
|
||||
end
|
||||
|
||||
local checked = false
|
||||
for i, child in ipairs(list:getChildren()) do
|
||||
if category == 1 and child.enabled:isChecked() or child:isChecked() then
|
||||
checked = true
|
||||
end
|
||||
end
|
||||
|
||||
if not checked then
|
||||
label:setColor("#d9321f")
|
||||
label:setTooltip("! WARNING ! \nNo category selected!")
|
||||
else
|
||||
label:setColor("#dfdfdf")
|
||||
label:setTooltip("")
|
||||
end
|
||||
end
|
||||
-- targetSettings
|
||||
targetSettings.vocations.box.knights:setChecked(config.conditions.knights)
|
||||
targetSettings.vocations.box.knights.onClick = function(widget)
|
||||
config.conditions.knights = not config.conditions.knights
|
||||
widget:setChecked(config.conditions.knights)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.paladins:setChecked(config.conditions.paladins)
|
||||
targetSettings.vocations.box.paladins.onClick = function(widget)
|
||||
config.conditions.paladins = not config.conditions.paladins
|
||||
widget:setChecked(config.conditions.paladins)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.druids:setChecked(config.conditions.druids)
|
||||
targetSettings.vocations.box.druids.onClick = function(widget)
|
||||
config.conditions.druids = not config.conditions.druids
|
||||
widget:setChecked(config.conditions.druids)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.sorcerers:setChecked(config.conditions.sorcerers)
|
||||
targetSettings.vocations.box.sorcerers.onClick = function(widget)
|
||||
config.conditions.sorcerers = not config.conditions.sorcerers
|
||||
widget:setChecked(config.conditions.sorcerers)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.friends:setChecked(config.conditions.friends)
|
||||
targetSettings.groups.box.friends.onClick = function(widget)
|
||||
config.conditions.friends = not config.conditions.friends
|
||||
widget:setChecked(config.conditions.friends)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.party:setChecked(config.conditions.party)
|
||||
targetSettings.groups.box.party.onClick = function(widget)
|
||||
config.conditions.party = not config.conditions.party
|
||||
widget:setChecked(config.conditions.party)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.guild:setChecked(config.conditions.guild)
|
||||
targetSettings.groups.box.guild.onClick = function(widget)
|
||||
config.conditions.guild = not config.conditions.guild
|
||||
widget:setChecked(config.conditions.guild)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.botserver:setChecked(config.conditions.botserver)
|
||||
targetSettings.groups.box.botserver.onClick = function(widget)
|
||||
config.conditions.botserver = not config.conditions.botserver
|
||||
widget:setChecked(config.conditions.botserver)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
validate(targetSettings.vocations.box.knights)
|
||||
validate(targetSettings.groups.box.friends)
|
||||
validate(targetSettings.vocations.box.sorcerers, 2)
|
||||
|
||||
-- conditions
|
||||
for i, setting in ipairs(config.settings) do
|
||||
local widget = UI.createWidget(setting.type, conditions.box)
|
||||
local text = setting.text
|
||||
local val = setting.value
|
||||
widget.text:setText(text)
|
||||
|
||||
if setting.type == "HealScroll" then
|
||||
widget.text:setText(widget.text:getText()..val)
|
||||
if not (text:find("Range") or text:find("Mas Res")) then
|
||||
widget.text:setText(widget.text:getText().."%")
|
||||
end
|
||||
widget.scroll:setValue(val)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
setting.value = value
|
||||
widget.text:setText(text..value)
|
||||
if not (text:find("Range") or text:find("Mas Res")) then
|
||||
widget.text:setText(widget.text:getText().."%")
|
||||
end
|
||||
end
|
||||
if text:find("Range") or text:find("Mas Res") then
|
||||
widget.scroll:setMaximum(10)
|
||||
end
|
||||
else
|
||||
widget.item:setItemId(val)
|
||||
widget.item:setShowCount(false)
|
||||
widget.item.onItemChange = function(widget)
|
||||
setting.value = widget:getItemId()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- priority and toggles
|
||||
local function setCrementalButtons()
|
||||
for i, child in ipairs(priority.list:getChildren()) do
|
||||
if i == 1 then
|
||||
child.increment:disable()
|
||||
elseif i == 6 then
|
||||
child.decrement:disable()
|
||||
else
|
||||
child.increment:enable()
|
||||
child.decrement:enable()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, action in ipairs(config.priorities) do
|
||||
local widget = UI.createWidget("PriorityEntry", priority.list)
|
||||
|
||||
widget:setText(action.name)
|
||||
widget.increment.onClick = function()
|
||||
local index = priority.list:getChildIndex(widget)
|
||||
local table = config.priorities
|
||||
|
||||
priority.list:moveChildToIndex(widget, index-1)
|
||||
table[index], table[index-1] = table[index-1], table[index]
|
||||
setCrementalButtons()
|
||||
end
|
||||
widget.decrement.onClick = function()
|
||||
local index = priority.list:getChildIndex(widget)
|
||||
local table = config.priorities
|
||||
|
||||
priority.list:moveChildToIndex(widget, index+1)
|
||||
table[index], table[index+1] = table[index+1], table[index]
|
||||
setCrementalButtons()
|
||||
end
|
||||
widget.enabled:setChecked(action.enabled)
|
||||
widget:setColor(action.enabled and "#98BF64" or "#dfdfdf")
|
||||
widget.enabled.onClick = function()
|
||||
action.enabled = not action.enabled
|
||||
widget:setColor(action.enabled and "#98BF64" or "#dfdfdf")
|
||||
widget.enabled:setChecked(action.enabled)
|
||||
validate(widget, 1)
|
||||
end
|
||||
if action.custom then
|
||||
widget.onDoubleClick = function()
|
||||
local window = modules.client_textedit.show(widget, {title = "Custom Spell", description = "Enter below formula for a custom healing spell"})
|
||||
schedule(50, function()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end)
|
||||
end
|
||||
widget.onTextChange = function(widget,text)
|
||||
action.name = text
|
||||
end
|
||||
widget:setTooltip("Double click to set spell formula.")
|
||||
end
|
||||
|
||||
if i == #config.priorities then
|
||||
validate(widget, 1)
|
||||
setCrementalButtons()
|
||||
end
|
||||
end
|
||||
|
||||
local lastItemUse = now
|
||||
local function friendHealerAction(spec, targetsInRange)
|
||||
local name = spec:getName()
|
||||
local health = spec:getHealthPercent()
|
||||
local mana = spec:getManaPercent()
|
||||
local dist = distanceFromPlayer(spec:getPosition())
|
||||
targetsInRange = targetsInRange or 0
|
||||
|
||||
local masResAmount = config.settings[4].value
|
||||
local itemRange = config.settings[2].value
|
||||
local healItem = config.settings[3].value
|
||||
local manaItem = config.settings[1].value
|
||||
local normalHeal = config.customPlayers[name] or config.settings[5].value
|
||||
local strongHeal = config.customPlayers[name] and normalHeal/2 or config.settings[6].value
|
||||
|
||||
for i, action in ipairs(config.priorities) do
|
||||
if action.enabled then
|
||||
if action.area and masResAmount <= targetsInRange and canCast("exura gran mas res") then
|
||||
return say("exura gran mas res")
|
||||
end
|
||||
if action.mana and findItem(manaItem) and mana <= normalHeal and dist <= itemRange and now - lastItemUse > 1000 then
|
||||
lastItemUse = now
|
||||
return useWith(manaItem, spec)
|
||||
end
|
||||
if action.health and findItem(healItem) and health <= normalHeal and dist <= itemRange and now - lastItemUse > 1000 then
|
||||
lastItemUse = now
|
||||
return useWith(healItem, spec)
|
||||
end
|
||||
if action.strong and health <= strongHeal and not modules.game_cooldown.isCooldownIconActive(101) then
|
||||
return say('exura gran sio "'..name)
|
||||
end
|
||||
if (action.normal or action.custom) and health <= normalHeal and canCast('exura sio "'..name) then
|
||||
return say('exura sio "'..name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function isCandidate(spec)
|
||||
if spec:isLocalPlayer() or not spec:isPlayer() then
|
||||
return nil
|
||||
end
|
||||
if not spec:canShoot() then
|
||||
return false
|
||||
end
|
||||
|
||||
local curHp = spec:getHealthPercent()
|
||||
if curHp == 100 or (config.customPlayers[name] and curHp > config.customPlayers[name]) then
|
||||
return false
|
||||
end
|
||||
|
||||
local specText = spec:getText()
|
||||
local name = spec:getName()
|
||||
-- check players is enabled and spectator already verified
|
||||
if storage.extras.checkPlayer and specText:len() > 0 then
|
||||
if specText:find("EK") and not config.conditions.knights or
|
||||
specText:find("RP") and not config.conditions.paladins or
|
||||
specText:find("ED") and not config.conditions.druids or
|
||||
specText:find("MS") and not config.conditions.sorcerers then
|
||||
if not config.customPlayers[name] then
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local okParty = config.conditions.party and spec:isPartyMember()
|
||||
local okFriend = config.conditions.friends and isFriend(spec)
|
||||
local okGuild = config.conditions.guild and spec:getEmblem() == 1
|
||||
local okBotServer = config.conditions.botserver and vBot.BotServerMembers[spec:getName()]
|
||||
|
||||
if not (okParty or okFriend or okGuild or okBotServer) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local health = config.customPlayers[name] and curHp/2 or curHp
|
||||
local dist = distanceFromPlayer(spec:getPosition())
|
||||
|
||||
return health, dist
|
||||
end
|
||||
|
||||
macro(100, function()
|
||||
if not config.enabled then return end
|
||||
if modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
|
||||
local minHp = config.settings[7].value
|
||||
local minMp = config.settings[8].value
|
||||
|
||||
local healTarget = {creature=nil, hp=100}
|
||||
local inMasResRange = 0
|
||||
|
||||
-- check basic
|
||||
if hppercent() <= minHp or manapercent() <= minMp then return end
|
||||
|
||||
-- get all spectators
|
||||
local spectators = getSpectators()
|
||||
|
||||
-- main check
|
||||
local healtR
|
||||
for i, spec in ipairs(spectators) do
|
||||
local health, dist = isCandidate(spec)
|
||||
--mas san
|
||||
if dist then
|
||||
inMasResRange = dist <= 3 and inMasResRange+1 or inMasResRange
|
||||
|
||||
-- best target
|
||||
if health < healTarget.hp then
|
||||
healTarget = {creature = spec, hp = health}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- action
|
||||
if healTarget.creature then
|
||||
return friendHealerAction(healTarget.creature, inMasResRange)
|
||||
end
|
||||
end)
|
413
modules/game_bot/default_configs/vBot_4.8/vBot/new_healer.otui
Normal file
@ -0,0 +1,413 @@
|
||||
CategoryCheckBox < CheckBox
|
||||
font: verdana-11px-rounded
|
||||
margin-top: 3
|
||||
|
||||
$checked:
|
||||
color: #98BF64
|
||||
|
||||
HealScroll < Panel
|
||||
|
||||
ToolTipLabel
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: test
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HealItem < Panel
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 34 34
|
||||
|
||||
ToolTipLabel
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.left: prev.right
|
||||
margin-left: 8
|
||||
text-wrap: true
|
||||
text-align: left
|
||||
|
||||
ToolTipLabel < UIWidget
|
||||
font: verdana-11px-rounded
|
||||
color: #dfdfdf
|
||||
height: 14
|
||||
text-align: center
|
||||
|
||||
HealerPlayerEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 5 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 15 15
|
||||
margin-right: 15
|
||||
text: X
|
||||
tooltip: Remove player from the list
|
||||
|
||||
PriorityEntry < ToolTipLabel
|
||||
background-color: alpha
|
||||
text-offset: 18 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 15 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
Button
|
||||
id: increment
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 14 14
|
||||
text: +
|
||||
tooltip: Increase Priority
|
||||
|
||||
Button
|
||||
id: decrement
|
||||
anchors.right: prev.left
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 14 14
|
||||
text: -
|
||||
tooltip: Decrease Priority
|
||||
|
||||
TargetSettings < Panel
|
||||
size: 280 125
|
||||
padding: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
Label
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Heal Target Settings
|
||||
|
||||
Groups
|
||||
id: groups
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 8
|
||||
anchors.left: parent.left
|
||||
margin-left: 9
|
||||
|
||||
Vocations
|
||||
id: vocations
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
|
||||
Groups < FlatPanel
|
||||
size: 150 90
|
||||
padding: 3
|
||||
padding-top: 5
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
text: Groups
|
||||
tooltip: Players added in custom list will always be in scope
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 2
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
CategoryCheckBox
|
||||
id: friends
|
||||
text: Friends
|
||||
|
||||
CategoryCheckBox
|
||||
id: party
|
||||
text: Party Members
|
||||
|
||||
CategoryCheckBox
|
||||
id: guild
|
||||
text: Guild Members
|
||||
|
||||
CategoryCheckBox
|
||||
id: botserver
|
||||
text: BotServer Members
|
||||
|
||||
Vocations < FlatPanel
|
||||
size: 100 90
|
||||
padding: 3
|
||||
padding-top: 5
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Vocations
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 2
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
CategoryCheckBox
|
||||
id: knights
|
||||
text: Knights
|
||||
|
||||
CategoryCheckBox
|
||||
id: paladins
|
||||
text: Paladins
|
||||
|
||||
CategoryCheckBox
|
||||
id: druids
|
||||
text: Druids
|
||||
|
||||
CategoryCheckBox
|
||||
id: sorcerers
|
||||
text: Sorcerers
|
||||
|
||||
Priority < Panel
|
||||
size: 190 123
|
||||
padding: 6
|
||||
padding-top: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Priority & Toggles
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
fit-children: true
|
||||
padding-top: 1
|
||||
|
||||
AddPlayer < FlatPanel
|
||||
padding: 5
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text: Add Player to Custom List
|
||||
text-align: center
|
||||
text-wrap: true
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
|
||||
SpinBox
|
||||
id: health
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
width: 50
|
||||
minimum: 1
|
||||
maximum: 99
|
||||
step: 1
|
||||
focusable: true
|
||||
text-align: center
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
font: verdana-11px-rounded
|
||||
text: %HP - heal if below
|
||||
|
||||
TextEdit
|
||||
id: name
|
||||
anchors.top: health.bottom
|
||||
margin-top: 5
|
||||
anchors.left: health.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text-align: center
|
||||
text: friend name
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.left: health.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
font: verdana-11px-rounded
|
||||
text: Add Player
|
||||
|
||||
PlayerList < Panel
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
fit-children: true
|
||||
padding-top: 2
|
||||
vertical-scrollbar: listScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
CustomList < Panel
|
||||
size: 190 172
|
||||
padding: 6
|
||||
padding-top: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
ToolTipLabel
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Custom Player List
|
||||
tooltip: Double click on the list below to add new player.
|
||||
|
||||
AddPlayer
|
||||
id: addPanel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
PlayerList
|
||||
id: playerList
|
||||
anchors.fill: prev
|
||||
|
||||
Conditions < Panel
|
||||
size: 280 170
|
||||
padding: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
Label
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Player Conditions
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.fill: parent
|
||||
margin-top: 16
|
||||
padding: 5
|
||||
padding-top: 3
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 128 31
|
||||
cell-spacing: 5
|
||||
num-columns: 2
|
||||
|
||||
FriendHealer < MainWindow
|
||||
!text: tr('Friend Healer')
|
||||
size: 512 390
|
||||
padding-top: 30
|
||||
@onEscape: self:hide()
|
||||
|
||||
Conditions
|
||||
id: conditions
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
TargetSettings
|
||||
id: targetSettings
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: prev.left
|
||||
|
||||
Priority
|
||||
id: priority
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
CustomList
|
||||
id: customList
|
||||
anchors.top: priority.bottom
|
||||
margin-top: 10
|
||||
anchors.left: priority.left
|
||||
|
||||
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
|
||||
@onClick: self:getParent():hide()
|
@ -0,0 +1,5 @@
|
||||
onAttackingCreatureChange(function(creature, OldCreature)
|
||||
if creature and creature:isNpc() and distanceFromPlayer(creature:getPosition()) <= 3 then
|
||||
CaveBot.Conversation("hi", "trade")
|
||||
end
|
||||
end)
|
351
modules/game_bot/default_configs/vBot_4.8/vBot/playerlist.lua
Normal file
@ -0,0 +1,351 @@
|
||||
--[[
|
||||
configuration for check players
|
||||
example made on server Gunzodus
|
||||
|
||||
example link for player overview:
|
||||
https://www.gunzodus.net/character/show/Sir_Vithrax
|
||||
|
||||
*note that space in character name was replaced with underscore (_) - this character will be important
|
||||
|
||||
in this case:
|
||||
link = "https://www.gunzodus.net/character/show/" -- everything with all the characters up to the start of the name
|
||||
spacing = "_" -- space replacement in character name
|
||||
]]
|
||||
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
local spacing = "_"
|
||||
|
||||
|
||||
|
||||
-- do not edit below
|
||||
setDefaultTab("Main")
|
||||
local tabs = {"Friends", "Enemies", "BlackList"}
|
||||
local panelName = "playerList"
|
||||
local colors = {"#03C04A", "#fc4c4e", "orange"}
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enemyList = {},
|
||||
friendList = {},
|
||||
blackList = {},
|
||||
groupMembers = true,
|
||||
outfits = false,
|
||||
marks = false,
|
||||
highlight = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
local playerTables = {config.friendList, config.enemyList, config.blackList}
|
||||
|
||||
-- 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
|
||||
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
local ListWindow = UI.createWindow('PlayerListWindow', rootWidget)
|
||||
ListWindow:hide()
|
||||
|
||||
UI.Button("Player Lists", function()
|
||||
ListWindow:show()
|
||||
ListWindow:raise()
|
||||
ListWindow:focus()
|
||||
end)
|
||||
|
||||
-- settings
|
||||
ListWindow.settings.Members:setChecked(config.groupMembers)
|
||||
ListWindow.settings.Members.onClick = function(widget)
|
||||
config.groupMembers = not config.groupMembers
|
||||
if not config.groupMembers then
|
||||
clearCachedPlayers()
|
||||
end
|
||||
refreshStatus()
|
||||
widget:setChecked(config.groupMembers)
|
||||
end
|
||||
ListWindow.settings.Outfit:setChecked(config.outfits)
|
||||
ListWindow.settings.Outfit.onClick = function(widget)
|
||||
config.outfits = not config.outfits
|
||||
widget:setChecked(config.outfits)
|
||||
refreshStatus()
|
||||
end
|
||||
ListWindow.settings.NeutralsAreEnemy:setChecked(config.marks)
|
||||
ListWindow.settings.NeutralsAreEnemy.onClick = function(widget)
|
||||
config.marks = not config.marks
|
||||
widget:setChecked(config.marks)
|
||||
end
|
||||
ListWindow.settings.Highlight:setChecked(config.highlight)
|
||||
ListWindow.settings.Highlight.onClick = function(widget)
|
||||
config.highlight = not config.highlight
|
||||
widget:setChecked(config.highlight)
|
||||
end
|
||||
|
||||
ListWindow.settings.AutoAdd:setChecked(config.autoAdd)
|
||||
ListWindow.settings.AutoAdd.onClick = function(widget)
|
||||
config.autoAdd = not config.autoAdd
|
||||
widget:setChecked(config.autoAdd)
|
||||
end
|
||||
|
||||
local TabBar = ListWindow.tmpTabBar
|
||||
TabBar:setContentWidget(ListWindow.tmpTabContent)
|
||||
local blacklistList
|
||||
|
||||
for v = 1, 3 do
|
||||
local listPanel = g_ui.createWidget("tPanel") -- Creates Panel
|
||||
local playerList = playerTables[v]
|
||||
listPanel:setId(tabs[v].."Tab")
|
||||
TabBar:addTab(tabs[v], listPanel)
|
||||
|
||||
-- elements
|
||||
local addButton = listPanel.add
|
||||
local nameTab = listPanel.name
|
||||
local list = listPanel.list
|
||||
if v == 3 then
|
||||
blacklistList = list
|
||||
end
|
||||
|
||||
for i, name in ipairs(playerList) do
|
||||
local label = UI.createWidget("PlayerLabel", list)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
clearCachedPlayers()
|
||||
refreshStatus()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", spacing)
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tabButton = TabBar.buttonsPanel:getChildren()[v]
|
||||
|
||||
tabButton.onStyleApply = function(widget)
|
||||
if TabBar:getCurrentTab() == widget then
|
||||
widget:setColor(colors[v])
|
||||
end
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
addButton.onClick = function()
|
||||
local names = string.split(nameTab:getText(), ",")
|
||||
|
||||
if #names == 0 then
|
||||
warn("vBot[PlayerList]: Name is missing!")
|
||||
return
|
||||
end
|
||||
|
||||
for i=1,#names do
|
||||
local name = names[i]:trim()
|
||||
if name:len() == 0 then
|
||||
warn("vBot[PlayerList]: Name is missing!")
|
||||
else
|
||||
if not table.find(playerList, name) then
|
||||
table.insert(playerList, name)
|
||||
local label = UI.createWidget("PlayerLabel", list)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", "_")
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
nameTab:setText("")
|
||||
else
|
||||
warn("vBot[PlayerList]: Player ".. name .." is already added!")
|
||||
nameTab:setText("")
|
||||
end
|
||||
clearCachedPlayers()
|
||||
refreshStatus()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nameTab.onKeyPress = function(widget, keyCode, keyboardModifiers)
|
||||
if keyCode ~= 5 then
|
||||
return false
|
||||
end
|
||||
addButton.onClick()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function addBlackListPlayer(name)
|
||||
if table.find(config.blackList, name) then return end
|
||||
|
||||
table.insert(config.blackList, name)
|
||||
local label = UI.createWidget("PlayerLabel", blacklistList)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", "_")
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onTextMessage(function(mode,text)
|
||||
if not config.autoAdd then return end
|
||||
if CaveBot.isOff() or TargetBot.isOff() then return end
|
||||
if not text:find("Warning! The murder of") then return end
|
||||
|
||||
text = string.split(text, "Warning! The murder of ")[1]
|
||||
text = string.split(text, " was not justified.")[1]
|
||||
|
||||
addBlackListPlayer(text)
|
||||
end)
|
||||
|
||||
onCreatureAppear(function(creature)
|
||||
checkStatus(creature)
|
||||
end)
|
||||
|
||||
onPlayerPositionChange(function(x,y)
|
||||
if x.z ~= y.z then
|
||||
schedule(20, function()
|
||||
refreshStatus()
|
||||
end)
|
||||
end
|
||||
end)
|