Updated to OTCv8 3.0 rev 83

This commit is contained in:
OTCv8 2021-05-26 23:26:45 +00:00
parent f769ffeda1
commit 86036d71f1
86 changed files with 1105 additions and 622 deletions

View File

@ -1,146 +0,0 @@
setDefaultTab("Main")
BotPanelName = "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(BotPanelName)
if not storage[BotPanelName] then
storage[BotPanelName] = {
manaInfo = true,
mwallInfo = true
}
end
if not storage.BotServerChannel then
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
end
local channel = tostring(storage.BotServerChannel)
BotServer.init(name(), channel)
rootWidget = g_ui.getRootWidget()
if rootWidget then
botServerWindow = g_ui.createWidget('BotServerWindow', rootWidget)
botServerWindow:hide()
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(storage[BotPanelName].manaInfo)
botServerWindow.Features.Feature1.onClick = function(widget)
storage[BotPanelName].manaInfo = not storage[BotPanelName].manaInfo
widget:setOn(storage[BotPanelName].manaInfo)
end
botServerWindow.Features.Feature2:setOn(storage[BotPanelName].mwallInfo)
botServerWindow.Features.Feature2.onClick = function(widget)
storage[BotPanelName].mwallInfo = not storage[BotPanelName].mwallInfo
widget:setOn(storage[BotPanelName].mwallInfo)
end
end
function updateStatusText()
if BotServer._websocket then
botServerWindow.Data.ServerStatus:setText("CONNECTED")
if serverCount then
botServerWindow.Data.Participants:setText(#serverCount)
end
else
botServerWindow.Data.ServerStatus:setText("DISCONNECTED")
botServerWindow.Data.Participants:setText("-")
end
end
macro(2000, function()
if BotServer._websocket then
BotServer.send("list")
end
updateStatusText()
end)
local regex = [["(.*?)"]]
BotServer.listen("list", function(name, data)
serverCount = regexMatch(json.encode(data), regex)
storage.serverMembers = json.encode(data)
end)
ui.botServer.onClick = function(widget)
botServerWindow:show()
botServerWindow:raise()
botServerWindow:focus()
end
botServerWindow.closeButton.onClick = function(widget)
botServerWindow:hide()
end
-- scripts
storage[BotPanelName].mwalls = {}
BotServer.listen("mwall", function(name, message)
if storage[BotPanelName].mwallInfo then
if not storage[BotPanelName].mwalls[message["pos"]] or storage[BotPanelName].mwalls[message["pos"]] < now then
storage[BotPanelName].mwalls[message["pos"]] = now + message["duration"] - 150 -- 150 is latency correction
end
end
end)
BotServer.listen("mana", function(name, message)
if storage[BotPanelName].manaInfo then
local creature = getPlayerByName(name)
if creature then
creature:setManaPercent(message["mana"])
end
end
end)
onAddThing(function(tile, thing)
if storage[BotPanelName].mwallInfo then
if thing:isItem() and thing:getId() == 2129 then
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
if not storage[BotPanelName].mwalls[pos] or storage[BotPanelName].mwalls[pos] < now then
storage[BotPanelName].mwalls[pos] = now + 20000
BotServer.send("mwall", {pos=pos, duration=20000})
end
end
end
end)
local lastMana = 0
macro(100, function()
if storage[BotPanelName].manaInfo then
if manapercent() ~= lastMana then
lastMana = manapercent()
BotServer.send("mana", {mana=lastMana})
end
end
end)
addSeparator()

View File

@ -1,124 +0,0 @@
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,
spellName = "exura sio",
spellHeal = true,
distance = 8,
itemHeal = true,
id = 3160
}
end
rootWidget = g_ui.getRootWidget()
sioListWindow = UI.createWindow('SioListWindow', rootWidget)
sioListWindow:hide()
ui.title:setOn(storage[panelName].enabled)
sioListWindow.spell:setOn(storage[panelName].spellHeal)
sioListWindow.item:setOn(storage[panelName].itemHeal)
ui.title.onClick = function(widget)
storage[panelName].enabled = not storage[panelName].enabled
widget:setOn(storage[panelName].enabled)
end
ui.editList.onClick = function(widget)
sioListWindow:show()
sioListWindow:raise()
sioListWindow:focus()
end
sioListWindow.spell.onClick = function(widget)
storage[panelName].spellHeal = not storage[panelName].spellHeal
widget:setOn(storage[panelName].spellHeal)
end
sioListWindow.item.onClick = function(widget)
storage[panelName].itemHeal = not storage[panelName].itemHeal
widget:setOn(storage[panelName].itemHeal)
end
sioListWindow.closeButton.onClick = function(widget)
sioListWindow:hide()
end
sioListWindow.spellName.onTextChange = function(widget, text)
storage[panelName].spellName = text
end
local updateMinManaText = function()
sioListWindow.manaInfo:setText("Minimum Mana >= " .. storage[panelName].minMana .. "%")
end
local updateFriendHpText = function()
sioListWindow.friendHp:setText("Heal Friend Below " .. storage[panelName].minFriendHp .. "% hp")
end
local updateDistanceText = function()
sioListWindow.distText:setText("Max Distance: " .. storage[panelName].distance)
end
sioListWindow.Distance.onValueChange = function(scroll, value)
storage[panelName].distance = value
updateDistanceText()
end
updateDistanceText()
sioListWindow.minMana.onValueChange = function(scroll, value)
storage[panelName].minMana = value
updateMinManaText()
end
sioListWindow.minFriendHp.onValueChange = function(scroll, value)
storage[panelName].minFriendHp = value
updateFriendHpText()
end
sioListWindow.itemId:setItemId(storage[panelName].id)
sioListWindow.itemId.onItemChange = function(widget)
storage[panelName].id = widget:getItemId()
end
sioListWindow.spellName:setText(storage[panelName].spellName)
sioListWindow.minMana:setValue(storage[panelName].minMana)
sioListWindow.minFriendHp:setValue(storage[panelName].minFriendHp)
sioListWindow.Distance:setValue(storage[panelName].distance)
local healItem
macro(200, function()
if storage[panelName].enabled and storage[panelName].spellName:len() > 0 and manapercent() > storage[panelName].minMana then
for _, spec in ipairs(getSpectators()) do
if not spec:isLocalPlayer() then
if spec:isPlayer() and storage[panelName].minFriendHp >= spec:getHealthPercent() and isFriend(spec:getName()) then
if storage[panelName].spellHeal then
saySpell(storage[panelName].spellName .. ' "' .. spec:getName(), 100)
return
end
healItem = findItem(storage[panelName].id)
if storage[panelName].itemHeal and distanceFromPlayer(spec:getPosition()) <= storage[panelName].distance and healItem then
useWith(storage[panelName].id, spec)
return
end
end
end
end
end
end)
addSeparator()

View File

@ -1,211 +0,0 @@
setDefaultTab("Main")
local listPanelName = "playerList"
local ui = setupUI([[
Panel
height: 18
Button
id: editList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
background: #292A2A
height: 18
text: Player Lists
]], parent)
ui:setId(listPanelName)
if not storage[listPanelName] then
storage[listPanelName] = {
enemyList = {},
friendList = {},
blackList = {},
groupMembers = true,
outfits = false,
marks = false
}
end
-- for backward compability
if not storage[listPanelName].blackList then
storage[listPanelName].blackList = {}
end
rootWidget = g_ui.getRootWidget()
playerListWindow = g_ui.createWidget('PlayerListsWindow', rootWidget)
playerListWindow:hide()
playerListWindow.Members:setOn(storage[listPanelName].groupMembers)
playerListWindow.Members.onClick = function(widget)
storage[listPanelName].groupMembers = not storage[listPanelName].groupMembers
widget:setOn(storage[listPanelName].groupMembers)
end
playerListWindow.Outfit:setOn(storage[listPanelName].outfits)
playerListWindow.Outfit.onClick = function(widget)
storage[listPanelName].outfits = not storage[listPanelName].outfits
widget:setOn(storage[listPanelName].outfits)
end
playerListWindow.Marks:setOn(storage[listPanelName].marks)
playerListWindow.Marks.onClick = function(widget)
storage[listPanelName].marks = not storage[listPanelName].marks
widget:setOn(storage[listPanelName].marks)
end
if storage[listPanelName].enemyList and #storage[listPanelName].enemyList > 0 then
for _, name in ipairs(storage[listPanelName].enemyList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].enemyList, label:getText())
label:destroy()
end
label:setText(name)
end
end
if storage[listPanelName].blackList and #storage[listPanelName].blackList > 0 then
for _, name in ipairs(storage[listPanelName].blackList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.BlackList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].blackList, label:getText())
label:destroy()
end
label:setText(name)
end
end
playerListWindow.AddEnemy.onClick = function(widget)
local friendName = playerListWindow.FriendName:getText()
if friendName:len() > 0 and not table.contains(storage[listPanelName].enemyList, friendName, true) then
table.insert(storage[listPanelName].enemyList, friendName)
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].enemyList, label:getText())
label:destroy()
end
label:setText(friendName)
playerListWindow.FriendName:setText('')
end
end
if storage[listPanelName].friendList and #storage[listPanelName].friendList > 0 then
for _, name in ipairs(storage[listPanelName].friendList) do
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].friendList, label:getText())
label:destroy()
end
label:setText(name)
end
end
playerListWindow.AddFriend.onClick = function(widget)
local friendName = playerListWindow.FriendName:getText()
if friendName:len() > 0 and not table.contains(storage[listPanelName].friendList, friendName, true) then
table.insert(storage[listPanelName].friendList, friendName)
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].friendList, label:getText())
label:destroy()
end
label:setText(friendName)
playerListWindow.FriendName:setText('')
end
end
playerListWindow.AddEnemy.onClick = function(widget)
local enemyName = playerListWindow.EnemyName:getText()
if enemyName:len() > 0 and not table.contains(storage[listPanelName].enemyList, enemyName, true) then
table.insert(storage[listPanelName].enemyList, enemyName)
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].enemyList, label:getText())
label:destroy()
end
label:setText(enemyName)
playerListWindow.EnemyName:setText('')
end
end
playerListWindow.AddBlack.onClick = function(widget)
local blackName = playerListWindow.BlackName:getText()
if blackName:len() > 0 and not table.contains(storage[listPanelName].blackList, blackName, true) then
table.insert(storage[listPanelName].blackList, blackName)
local label = g_ui.createWidget("PlayerName", playerListWindow.BlackList)
label.remove.onClick = function(widget)
table.removevalue(storage[listPanelName].blackList, label:getText())
label:destroy()
end
label:setText(blackName)
playerListWindow.BlackName:setText('')
refreshStatus()
end
end
ui.editList.onClick = function(widget)
playerListWindow:show()
playerListWindow:raise()
playerListWindow:focus()
end
playerListWindow.closeButton.onClick = function(widget)
playerListWindow:hide()
end
local refreshStatus = function()
for _, spec in ipairs(getSpectators()) do
if spec:isPlayer() and not spec:isLocalPlayer() then
if storage[listPanelName].outfits then
local specOutfit = spec:getOutfit()
if isFriend(spec:getName()) then
spec:setMarked('#0000FF')
specOutfit.head = 88
specOutfit.body = 88
specOutfit.legs = 88
specOutfit.feet = 88
spec:setOutfit(specOutfit)
elseif isEnemy(spec:getName()) then
spec:setMarked('#FF0000')
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
creature:setMarked('#0000FF')
specOutfit.head = 88
specOutfit.body = 88
specOutfit.legs = 88
specOutfit.feet = 88
creature:setOutfit(specOutfit)
elseif isEnemy(specName) then
creature:setMarked('#FF0000')
specOutfit.head = 94
specOutfit.body = 94
specOutfit.legs = 94
specOutfit.feet = 94
creature:setOutfit(specOutfit)
end
end
onCreatureAppear(function(creature)
checkStatus(creature)
end)
onPlayerPositionChange(function(x,y)
if x.z ~= y.z then
schedule(20, function()
refreshStatus()
end)
end
end)

View File

@ -9,6 +9,10 @@ local function setup()
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z, true) CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z, true)
lastPos = pos lastPos = pos
end end
local function addStairs(pos)
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z .. ",0", true)
lastPos = pos
end
onPlayerPositionChange(function(newPos, oldPos) onPlayerPositionChange(function(newPos, oldPos)
if CaveBot.isOn() or not isEnabled then return end if CaveBot.isOn() or not isEnabled then return end
@ -17,7 +21,7 @@ local function setup()
addPosition(oldPos) addPosition(oldPos)
elseif newPos.z ~= oldPos.z or math.abs(oldPos.x - newPos.x) > 1 or math.abs(oldPos.y - newPos.y) > 1 then elseif newPos.z ~= oldPos.z or math.abs(oldPos.x - newPos.x) > 1 or math.abs(oldPos.y - newPos.y) > 1 then
-- stairs/teleport -- stairs/teleport
addPosition(oldPos) addStairs(oldPos)
elseif math.max(math.abs(lastPos.x - newPos.x), math.abs(lastPos.y - newPos.y)) > 5 then elseif math.max(math.abs(lastPos.x - newPos.x), math.abs(lastPos.y - newPos.y)) > 5 then
-- 5 steps from last pos -- 5 steps from last pos
addPosition(newPos) addPosition(newPos)

View File

@ -0,0 +1,203 @@
setDefaultTab("Main")
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]
if not storage.BotServerChannel then
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
end
local channel = tostring(storage.BotServerChannel)
BotServer.init(name(), channel)
BotServerMembers = {}
rootWidget = g_ui.getRootWidget()
if rootWidget then
botServerWindow = g_ui.createWidget('BotServerWindow', rootWidget)
botServerWindow:hide()
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 updateStatusText()
if BotServer._websocket then
botServerWindow.Data.ServerStatus:setText("CONNECTED")
if serverCount then
botServerWindow.Data.Members:setText("Members: "..#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")
botServerWindow.Data.Participants:setText("-")
end
end
macro(2000, function()
if BotServer._websocket then
BotServer.send("list")
end
updateStatusText()
end)
local regex = [["(.*?)"]]
BotServer.listen("list", function(name, data)
serverCount = regexMatch(json.encode(data), regex)
ServerMembers = json.encode(data)
end)
ui.botServer.onClick = function(widget)
botServerWindow:show()
botServerWindow:raise()
botServerWindow:focus()
end
botServerWindow.closeButton.onClick = function(widget)
botServerWindow:hide()
end
-- scripts
-- mwalls
config.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)
onAddThing(function(tile, thing)
if config.mwallInfo 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(100, function()
if config.manaInfo then
if manapercent() ~= lastMana then
lastMana = manapercent()
BotServer.send("mana", {mana=lastMana})
end
end
end)
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
if config.vocation then
BotServer.send("voc", player:getVocation())
BotServer.send("voc", "yes")
end
BotServer.listen("voc", function(name, message)
if message == "yes" and config.vocation then
BotServer.send("voc", player:getVocation())
else
BotServerMembers[name] = message
end
end)
-- broadcast
BotServer.listen("broadcast", function(name, message)
if config.broadcasts then
broadcastMessage(name..": "..message)
end
end)
addSeparator()

View File

@ -66,12 +66,11 @@ BotServerData < Panel
margin-bottom: 4 margin-bottom: 4
text-align: center text-align: center
Label UIWidget
id: label id: Members
anchors.right: Participants.left anchors.right: Participants.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin-right: 10 size: 80 21
margin-bottom: 4
text-align: center text-align: center
text: Members: text: Members:
@ -111,6 +110,50 @@ FeaturePanel < Panel
margin-left: 5 margin-left: 5
text: MWall info 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 BotServerWindow < MainWindow
!text: tr('BotServer') !text: tr('BotServer')
size: 370 310 size: 370 310

View File

@ -622,8 +622,8 @@ end)
-- items -- items
macro(100, function() macro(100, function()
if not currentSettings.enabled or #currentSettings.itemTable == 0 then return end if not currentSettings.enabled or #currentSettings.itemTable == 0 then return end
if currentSettings.Delay and HealBotConfig.isUsing then return end if currentSettings.Delay and storage.isUsing then return end
if currentSettings.MessageDelay and HealBotConfig.isUsingPotion then return end if currentSettings.MessageDelay and storage.isUsingPotion then return end
if not currentSettings.MessageDelay then if not currentSettings.MessageDelay then
delay(400) delay(400)

View 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.spellName)
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 = 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()

View 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

View File

@ -1,4 +1,7 @@
-- [[ test config part ]] -- --[[
Configs for modules
Based on Kondrah storage method
--]]
configName = modules.game_bot.contentsPanel.config:getCurrentOption().text configName = modules.game_bot.contentsPanel.config:getCurrentOption().text
-- make vBot config dir -- make vBot config dir
@ -48,35 +51,37 @@ if g_resources.fileExists(suppliesFile) then
end end
function vBotConfigSave(file) function vBotConfigSave(file)
-- file can be either -- file can be either
--- heal --- heal
--- atk --- atk
--- supply --- supply
local configFile local configFile
local configTable local configTable
if not file then return end if not file then return end
file = file:lower() file = file:lower()
if file == "heal" then if file == "heal" then
configFile = healBotFile configFile = healBotFile
configTable = HealBotConfig configTable = HealBotConfig
elseif file == "atk" then elseif file == "atk" then
configFile = attackBotFile configFile = attackBotFile
configTable = AttackBotConfig configTable = AttackBotConfig
elseif file == "supply" then elseif file == "supply" then
configFile = suppliesFile configFile = suppliesFile
configTable = SuppliesConfig configTable = SuppliesConfig
end else
return
end
local status, result = pcall(function() local status, result = pcall(function()
return json.encode(configTable, 2) return json.encode(configTable, 2)
end) end)
if not status then if not status then
return onError("Error while saving config. it won't be saved. Details: " .. result) return onError("Error while saving config. it won't be saved. Details: " .. result)
end end
if result:len() > 100 * 1024 * 1024 then if result:len() > 100 * 1024 * 1024 then
return onError("config file is too big, above 100MB, it won't be saved") return onError("config file is too big, above 100MB, it won't be saved")
end end
g_resources.writeFileContents(configFile, result) g_resources.writeFileContents(configFile, result)
end end

View File

@ -1,7 +1,5 @@
setDefaultTab("HP") setDefaultTab("HP")
UI.Separator()
UI.Label("Eatable items:") UI.Label("Eatable items:")
if type(storage.foodItems) ~= "table" then if type(storage.foodItems) ~= "table" then
storage.foodItems = {3582, 3577} storage.foodItems = {3582, 3577}
@ -26,4 +24,5 @@ macro(500, "Eat Food", function()
end end
end end
end end
end) end)
UI.Separator()

View File

@ -80,7 +80,7 @@ UI.Button("vBot Settings and Scripts", function()
end) end)
UI.Separator() UI.Separator()
-- to remain order, add options right after another: ---- to maintain order, add options right after another:
--- add object --- add object
--- add variables for function (optional) --- add variables for function (optional)
--- add callback (optional) --- add callback (optional)
@ -127,7 +127,7 @@ if true then
6257, 6256, 2772, 27260, 2773, 1632, 1633, 1948, 435, 6252, 6253, 5007, 4911, 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, 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, 31118, 20474, 5737, 5736, 5734, 5733, 31202, 31228, 31199, 31200, 33262, 30824,
5125, 5126, 5116, 5117, 8257, 8258, 8255, 8256} 5125, 5126, 5116, 5117, 8257, 8258, 8255, 8256, 5120, 30777, 30776}
local shovelId = {606, 593, 867} local shovelId = {606, 593, 867}
local ropeId = {17238, 12202, 12935, 386, 421, 21966, 14238} local ropeId = {17238, 12202, 12935, 386, 421, 21966, 14238}
local macheteId = {2130, 3696} local macheteId = {2130, 3696}
@ -207,7 +207,7 @@ end
addCheckBox("antiKick", "Anti - Kick", true, rightPanel) addCheckBox("antiKick", "Anti - Kick", true, rightPanel)
if true then if true then
macro(60*1000, function() macro(600*1000, function()
if not settings.antiKick then return end if not settings.antiKick then return end
local dir = player:getDirection() local dir = player:getDirection()
turn((dir + 1) % 4) turn((dir + 1) % 4)
@ -281,7 +281,7 @@ if true then
local doorsIds = { 5007, 8265, 1629, 1632, 5129, 6252, 6249, 7715, 7712, 7714, local doorsIds = { 5007, 8265, 1629, 1632, 5129, 6252, 6249, 7715, 7712, 7714,
7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642, 7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642,
6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116, 6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116,
1632, 11705, 30772, 30774, 6248, 5735, 5732 } 1632, 11705, 30772, 30774, 6248, 5735, 5732, 5120 }
function checkForDoors(pos) function checkForDoors(pos)
local tile = g_map.getTile(pos) local tile = g_map.getTile(pos)

View File

@ -116,7 +116,7 @@ local valueInSeconds = function(t)
return math.ceil(d/((now-time)/1000)) return math.ceil(d/((now-time)/1000))
end end
local regex = "You lose ([0-9]*) hitpoints due to an attack by ([a-z*]) ([a-z A-z-]*)" local regex = "You lose ([0-9]*) hitpoints due to an attack by ([a-z]*) ([a-z A-z-]*)"
onTextMessage(function(mode, text) onTextMessage(function(mode, text)
if mode == 21 then -- damage dealt if mode == 21 then -- damage dealt
totalDmg = totalDmg + getFirstNumberInText(text) totalDmg = totalDmg + getFirstNumberInText(text)

View File

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

View File

@ -17,7 +17,7 @@ PlayerName < Label
PlayerListsWindow < MainWindow PlayerListsWindow < MainWindow
!text: tr('Player Lists') !text: tr('Player Lists')
size: 570 350 size: 580 350
@onEscape: self:hide() @onEscape: self:hide()
Label Label
@ -37,7 +37,7 @@ PlayerListsWindow < MainWindow
margin-right: 3 margin-right: 3
padding: 1 padding: 1
width: 180 width: 180
height: 180 height: 160
vertical-scrollbar: FriendListScrollBar vertical-scrollbar: FriendListScrollBar
VerticalScrollBar VerticalScrollBar
@ -82,7 +82,7 @@ PlayerListsWindow < MainWindow
margin-left: 3 margin-left: 3
padding: 1 padding: 1
width: 180 width: 180
height: 180 height: 160
vertical-scrollbar: EnemyListScrollBar vertical-scrollbar: EnemyListScrollBar
VerticalScrollBar VerticalScrollBar
@ -127,7 +127,7 @@ PlayerListsWindow < MainWindow
margin-left: 3 margin-left: 3
padding: 1 padding: 1
width: 180 width: 180
height: 180 height: 160
vertical-scrollbar: BlackListScrollBar vertical-scrollbar: BlackListScrollBar
VerticalScrollBar VerticalScrollBar
@ -157,33 +157,39 @@ PlayerListsWindow < MainWindow
BotSwitch BotSwitch
id: Members id: Members
anchors.left: FriendList.left anchors.left: parent.left
anchors.right: FriendList.right
anchors.top: AddEnemy.bottom anchors.top: AddEnemy.bottom
margin-top: 10 margin-top: 15
width: 114 width: 135
text-align: center text-align: center
text: Group Members text: Group Members
BotSwitch BotSwitch
id: Outfit id: Outfit
anchors.left: EnemyList.left anchors.bottom: prev.bottom
anchors.right: EnemyList.right anchors.left: prev.right
anchors.top: AddEnemy.bottom margin-left: 3
margin-top: 10 width: 135
width: 114
text-align: center text-align: center
text: Color Outfits text: Color Outfits
BotSwitch BotSwitch
id: Marks id: Marks
anchors.left: BlackList.left anchors.bottom: prev.bottom
anchors.right: BlackList.right anchors.left: prev.right
anchors.top: AddEnemy.bottom width: 135
margin-top: 10 margin-left: 3
width: 114
text-align: center text-align: center
text: Not Ally = Enemy text: Not Ally = Enemy
BotSwitch
id: Highlight
anchors.bottom: prev.bottom
anchors.left: prev.right
width: 135
margin-left: 3
text-align: center
text: Highlight
HorizontalSeparator HorizontalSeparator
id: separator id: separator

View File

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

View File

@ -1,23 +1,97 @@
SioListWindow < MainWindow VocationPanel < Panel
!text: tr('Healer Options') padding: 3
size: 200 310 image-source: /images/ui/panel_flat
@onEscape: self:hide() image-border: 6
size: 190 55
BotSwitch Label
id: spell
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
text: Spell Healing text-align: center
text: for BotServer, Heal only:
BotSwitch
id: ED
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.horizontalCenter
text: Druids
BotSwitch
id: MS
anchors.bottom: parent.bottom
anchors.left: parent.horizontalCenter
anchors.right: parent.right
text: Sorcerers
BotSwitch
id: EK
anchors.bottom: ED.top
anchors.left: parent.left
anchors.right: parent.horizontalCenter
text: Knights
BotSwitch
id: RP
anchors.bottom: ED.top
anchors.left: parent.horizontalCenter
anchors.right: parent.right
text: Paladins
SioListWindow < MainWindow
!text: tr('Healer Options')
size: 220 360
@onEscape: self:hide()
BotSwitch
id: exuraSio
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.horizontalCenter
text: Exura Sio
margin-right: 2
BotSwitch
id: exuraGranSio
anchors.top: parent.top
anchors.left: prev.right
anchors.right: parent.right
text: Exura Gran Sio
margin-left: 2
BotSwitch
id: exuraMasRes
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
text: Exura Gran Mas Res
margin-top: 3
BotSwitch
id: spell
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
text: Custom Spell
margin-top: 3
text-align: center text-align: center
BotTextEdit BotTextEdit
id: spellName id: spellName
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: spell.bottom anchors.top: prev.bottom
margin-top: 3 margin-top: 3
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 10
BotItem BotItem
id: itemId id: itemId
anchors.top: prev.bottom anchors.top: prev.bottom
@ -53,13 +127,19 @@ SioListWindow < MainWindow
maximum: 10 maximum: 10
step: 1 step: 1
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 8
BotLabel BotLabel
id: manaInfo id: manaInfo
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: Distance.bottom anchors.top: prev.bottom
text-align: center text-align: center
margin-top: 15 margin-top: 5
HorizontalScrollBar HorizontalScrollBar
id: minMana id: minMana
@ -77,7 +157,7 @@ SioListWindow < MainWindow
anchors.right: spellName.right anchors.right: spellName.right
anchors.top: prev.bottom anchors.top: prev.bottom
text-align: center text-align: center
margin-top: 10 margin-top: 5
HorizontalScrollBar HorizontalScrollBar
id: minFriendHp id: minFriendHp
@ -87,7 +167,12 @@ SioListWindow < MainWindow
margin-top: 2 margin-top: 2
minimum: 1 minimum: 1
maximum: 100 maximum: 100
step: 1 step: 1
VocationPanel
id: vocation
anchors.top: prev.bottom
margin-top: 6
HorizontalSeparator HorizontalSeparator
id: separator id: separator

View File

@ -39,6 +39,32 @@ SuppliesConfig[suppliesPanelName] = {
} }
end end
-- data validation
local setup = SuppliesConfig[suppliesPanelName]
setup.item1 = setup.item1 or 0
setup.item2 = setup.item2 or 0
setup.item3 = setup.item3 or 0
setup.item4 = setup.item4 or 0
setup.item5 = setup.item5 or 0
setup.item6 = setup.item6 or 0
setup.item1Min = setup.item1Min or 0
setup.item1Max = setup.item1Max or 0
setup.item2Min = setup.item2Min or 0
setup.item2Max = setup.item2Max or 0
setup.item3Min = setup.item3Min or 0
setup.item3Max = setup.item3Max or 0
setup.item4Min = setup.item4Min or 0
setup.item4Max = setup.item4Max or 0
setup.item5Min = setup.item5Min or 0
setup.item5Max = setup.item5Max or 0
setup.item6Min = setup.item6Min or 0
setup.item6Max = setup.item6Max or 0
setup.capValue = setup.capValue or 0
setup.staminaValue = setup.staminaValue or 0
setup.potionBp = setup.potionBp or 0
setup.runeBp = setup.runeBp or 0
setup.ammoBp = setup.ammoBp or 0
rootWidget = g_ui.getRootWidget() rootWidget = g_ui.getRootWidget()
if rootWidget then if rootWidget then
SuppliesWindow = g_ui.createWidget('SuppliesWindow', rootWidget) SuppliesWindow = g_ui.createWidget('SuppliesWindow', rootWidget)
@ -127,8 +153,11 @@ if rootWidget then
local value = tonumber(SuppliesWindow.capValue:getText()) local value = tonumber(SuppliesWindow.capValue:getText())
if not value then if not value then
SuppliesWindow.capValue:setText(0) SuppliesWindow.capValue:setText(0)
SuppliesConfig[suppliesPanelName].capValue = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].capValue = text
end end
SuppliesConfig[suppliesPanelName].capValue = text
end end
SuppliesWindow.item1Min:setText(SuppliesConfig[suppliesPanelName].item1Min) SuppliesWindow.item1Min:setText(SuppliesConfig[suppliesPanelName].item1Min)
@ -136,8 +165,11 @@ end
local value = tonumber(SuppliesWindow.item1Min:getText()) local value = tonumber(SuppliesWindow.item1Min:getText())
if not value then if not value then
SuppliesWindow.item1Min:setText(0) SuppliesWindow.item1Min:setText(0)
SuppliesConfig[suppliesPanelName].item1Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item1Min = text
end end
SuppliesConfig[suppliesPanelName].item1Min = text
end end
SuppliesWindow.item1Max:setText(SuppliesConfig[suppliesPanelName].item1Max) SuppliesWindow.item1Max:setText(SuppliesConfig[suppliesPanelName].item1Max)
@ -145,8 +177,11 @@ end
local value = tonumber(SuppliesWindow.item1Max:getText()) local value = tonumber(SuppliesWindow.item1Max:getText())
if not value then if not value then
SuppliesWindow.item1Max:setText(0) SuppliesWindow.item1Max:setText(0)
SuppliesConfig[suppliesPanelName].item1Max = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item1Max = text
end end
SuppliesConfig[suppliesPanelName].item1Max = text
end end
SuppliesWindow.item2Min:setText(SuppliesConfig[suppliesPanelName].item2Min) SuppliesWindow.item2Min:setText(SuppliesConfig[suppliesPanelName].item2Min)
@ -154,8 +189,11 @@ end
local value = tonumber(SuppliesWindow.item2Min:getText()) local value = tonumber(SuppliesWindow.item2Min:getText())
if not value then if not value then
SuppliesWindow.item2Min:setText(0) SuppliesWindow.item2Min:setText(0)
SuppliesConfig[suppliesPanelName].item2Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item2Min = text
end end
SuppliesConfig[suppliesPanelName].item2Min = text
end end
SuppliesWindow.item2Max:setText(SuppliesConfig[suppliesPanelName].item2Max) SuppliesWindow.item2Max:setText(SuppliesConfig[suppliesPanelName].item2Max)
@ -163,8 +201,11 @@ end
local value = tonumber(SuppliesWindow.item2Max:getText()) local value = tonumber(SuppliesWindow.item2Max:getText())
if not value then if not value then
SuppliesWindow.item2Max:setText(0) SuppliesWindow.item2Max:setText(0)
SuppliesConfig[suppliesPanelName].item2Max = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item2Max = text
end end
SuppliesConfig[suppliesPanelName].item2Max = text
end end
SuppliesWindow.item3Min:setText(SuppliesConfig[suppliesPanelName].item3Min) SuppliesWindow.item3Min:setText(SuppliesConfig[suppliesPanelName].item3Min)
@ -172,8 +213,11 @@ end
local value = tonumber(SuppliesWindow.item3Min:getText()) local value = tonumber(SuppliesWindow.item3Min:getText())
if not value then if not value then
SuppliesWindow.item3Min:setText(0) SuppliesWindow.item3Min:setText(0)
SuppliesConfig[suppliesPanelName].item3Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item3Min = text
end end
SuppliesConfig[suppliesPanelName].item3Min = text
end end
SuppliesWindow.item3Max:setText(SuppliesConfig[suppliesPanelName].item3Max) SuppliesWindow.item3Max:setText(SuppliesConfig[suppliesPanelName].item3Max)
@ -181,8 +225,10 @@ end
local value = tonumber(SuppliesWindow.item3Max:getText()) local value = tonumber(SuppliesWindow.item3Max:getText())
if not value then if not value then
SuppliesWindow.item3Max:setText(0) SuppliesWindow.item3Max:setText(0)
SuppliesConfig[suppliesPanelName].item3Max = 0
else
SuppliesConfig[suppliesPanelName].item3Max = text
end end
SuppliesConfig[suppliesPanelName].item3Max = text
end end
SuppliesWindow.item4Min:setText(SuppliesConfig[suppliesPanelName].item4Min) SuppliesWindow.item4Min:setText(SuppliesConfig[suppliesPanelName].item4Min)
@ -190,8 +236,11 @@ end
local value = tonumber(SuppliesWindow.item4Min:getText()) local value = tonumber(SuppliesWindow.item4Min:getText())
if not value then if not value then
SuppliesWindow.item4Min:setText(0) SuppliesWindow.item4Min:setText(0)
SuppliesConfig[suppliesPanelName].item4Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item4Min = text
end end
SuppliesConfig[suppliesPanelName].item4Min = text
end end
SuppliesWindow.staminaValue:setText(SuppliesConfig[suppliesPanelName].staminaValue) SuppliesWindow.staminaValue:setText(SuppliesConfig[suppliesPanelName].staminaValue)
@ -199,8 +248,11 @@ SuppliesWindow.staminaValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.staminaValue:getText()) local value = tonumber(SuppliesWindow.staminaValue:getText())
if not value then if not value then
SuppliesWindow.staminaValue:setText(0) SuppliesWindow.staminaValue:setText(0)
SuppliesConfig[suppliesPanelName].staminaValue = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].staminaValue = text
end end
SuppliesConfig[suppliesPanelName].staminaValue = text
end end
SuppliesWindow.item4Max:setText(SuppliesConfig[suppliesPanelName].item4Max) SuppliesWindow.item4Max:setText(SuppliesConfig[suppliesPanelName].item4Max)
@ -208,35 +260,47 @@ end
local value = tonumber(SuppliesWindow.item4Max:getText()) local value = tonumber(SuppliesWindow.item4Max:getText())
if not value then if not value then
SuppliesWindow.item4Max:setText(0) SuppliesWindow.item4Max:setText(0)
SuppliesConfig[suppliesPanelName].item4Max = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item4Max = text
end end
SuppliesConfig[suppliesPanelName].item4Max = text end
end
SuppliesWindow.item5Min:setText(SuppliesConfig[suppliesPanelName].item5Min) SuppliesWindow.item5Min:setText(SuppliesConfig[suppliesPanelName].item5Min)
SuppliesWindow.item5Min.onTextChange = function(widget, text) SuppliesWindow.item5Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Min:getText()) local value = tonumber(SuppliesWindow.item5Min:getText())
if not value then if not value then
SuppliesWindow.item5Min:setText(0) SuppliesWindow.item5Min:setText(0)
SuppliesConfig[suppliesPanelName].item5Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item5Min = text
end end
SuppliesConfig[suppliesPanelName].item5Min = text end
end
SuppliesWindow.item5Max:setText(SuppliesConfig[suppliesPanelName].item5Max) SuppliesWindow.item5Max:setText(SuppliesConfig[suppliesPanelName].item5Max)
SuppliesWindow.item5Max.onTextChange = function(widget, text) SuppliesWindow.item5Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Max:getText()) local value = tonumber(SuppliesWindow.item5Max:getText())
if not value then if not value then
SuppliesWindow.item5Max:setText(0) SuppliesWindow.item5Max:setText(0)
SuppliesConfig[suppliesPanelName].item5Max = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item5Max = text
end end
SuppliesConfig[suppliesPanelName].item5Max = text end
end
SuppliesWindow.item6Min:setText(SuppliesConfig[suppliesPanelName].item6Min) SuppliesWindow.item6Min:setText(SuppliesConfig[suppliesPanelName].item6Min)
SuppliesWindow.item6Min.onTextChange = function(widget, text) SuppliesWindow.item6Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Min:getText()) local value = tonumber(SuppliesWindow.item6Min:getText())
if not value then if not value then
SuppliesWindow.item6Min:setText(0) SuppliesWindow.item6Min:setText(0)
SuppliesConfig[suppliesPanelName].item6Min = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item6Min = text
end end
SuppliesConfig[suppliesPanelName].item6Min = text
end end
SuppliesWindow.item6Max:setText(SuppliesConfig[suppliesPanelName].item6Max) SuppliesWindow.item6Max:setText(SuppliesConfig[suppliesPanelName].item6Max)
@ -244,8 +308,11 @@ SuppliesWindow.item6Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Max:getText()) local value = tonumber(SuppliesWindow.item6Max:getText())
if not value then if not value then
SuppliesWindow.item6Max:setText(0) SuppliesWindow.item6Max:setText(0)
SuppliesConfig[suppliesPanelName].item6Max = 0
else
text = text:match("0*(%d+)")
SuppliesConfig[suppliesPanelName].item6Max = text
end end
SuppliesConfig[suppliesPanelName].item6Max = text
end end
end end

View File

@ -46,7 +46,7 @@ SuppliesWindow < MainWindow
text-align: center text-align: center
text: Cap Below: text: Cap Below:
TextEdit BotTextEdit
id: capValue id: capValue
size: 40 20 size: 40 20
anchors.left: prev.right anchors.left: prev.right
@ -65,7 +65,7 @@ SuppliesWindow < MainWindow
text-align: center text-align: center
text: Stamina: text: Stamina:
TextEdit BotTextEdit
id: staminaValue id: staminaValue
size: 40 20 size: 40 20
anchors.left: prev.right anchors.left: prev.right
@ -152,7 +152,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item1Min id: item1Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -161,7 +161,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item1Max id: item1Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right
@ -189,7 +189,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item2Min id: item2Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -198,7 +198,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item2Max id: item2Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right
@ -226,7 +226,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item3Min id: item3Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -235,7 +235,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item3Max id: item3Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right
@ -263,7 +263,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item4Min id: item4Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -272,7 +272,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item4Max id: item4Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right
@ -300,7 +300,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item5Min id: item5Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -309,7 +309,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item5Max id: item5Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right
@ -337,7 +337,7 @@ SuppliesWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 35 margin-left: 35
TextEdit BotTextEdit
id: item6Min id: item6Min
size: 100 20 size: 100 20
anchors.left: parent.left anchors.left: parent.left
@ -346,7 +346,7 @@ SuppliesWindow < MainWindow
margin-left: 40 margin-left: 40
text-align: center text-align: center
TextEdit BotTextEdit
id: item6Max id: item6Max
size: 100 20 size: 100 20
anchors.left: prev.right anchors.left: prev.right

View File

@ -3,6 +3,10 @@
-- burst damage calculation, for function burstDamageValue() -- burst damage calculation, for function burstDamageValue()
-- sums monster hits on a span of last 3seconds -- sums monster hits on a span of last 3seconds
-- if last message was more than 3s ago then clears the table -- if last message was more than 3s ago then clears the table
-- initial global variables declaration
BotServerMembers = {}
local dmgTable = {} local dmgTable = {}
local lastDmgMessage = now local lastDmgMessage = now
onTextMessage(function(mode, text) onTextMessage(function(mode, text)
@ -42,6 +46,10 @@ function whiteInfoMessage(text)
return modules.game_textmessage.displayGameMessage(text) return modules.game_textmessage.displayGameMessage(text)
end end
function broadcastMessage(text)
return modules.game_textmessage.displayBroadcastMessage(text)
end
-- almost every talk action inside cavebot has to be done by using schedule -- almost every talk action inside cavebot has to be done by using schedule
-- therefore this is simplified function that doesn't require to build a body for schedule function -- therefore this is simplified function that doesn't require to build a body for schedule function
function scheduleNpcSay(text, delay) function scheduleNpcSay(text, delay)
@ -183,6 +191,7 @@ end)
SpellCastTable = {} SpellCastTable = {}
onTalk(function(name, level, mode, text, channelId, pos) onTalk(function(name, level, mode, text, channelId, pos)
if name ~= player:getName() then return end if name ~= player:getName() then return end
text = text:lower()
if SpellCastTable[text] then SpellCastTable[text].t = now end if SpellCastTable[text] then SpellCastTable[text].t = now end
end) end)
@ -190,6 +199,7 @@ end)
-- if delay is nil or delay is lower than 100 then this function will act as a normal say function -- if delay is nil or delay is lower than 100 then this function will act as a normal say function
-- checks or adds a spell to SpellCastTable and updates cast time if exist -- checks or adds a spell to SpellCastTable and updates cast time if exist
function cast(text, delay) function cast(text, delay)
text = text:lower()
if type(text) ~= "string" then return end if type(text) ~= "string" then return end
if not delay or delay < 100 then if not delay or delay < 100 then
return say(text) -- if not added delay or delay is really low then just treat it like casual say return say(text) -- if not added delay or delay is really low then just treat it like casual say
@ -213,24 +223,24 @@ local Spells = modules.gamelib.SpellInfo['Default']
function canCast(spell, ignoreRL, ignoreCd) function canCast(spell, ignoreRL, ignoreCd)
if type(spell) ~= "string" then return end if type(spell) ~= "string" then return end
spell = spell:lower() spell = spell:lower()
if not getSpellData(spell) then if SpellCastTable[spell] then
if SpellCastTable[spell] then if now - SpellCastTable[spell].t > SpellCastTable[spell].d or ignoreCd then
if now - SpellCastTable[spell].t > SpellCastTable[spell].d then
return true
else
return false
end
else
return true return true
else
return false
end end
end end
if (ignoreCd or not getSpellCoolDown(spell)) and if getSpellData(spell) then
(ignoreRL or level() >= getSpellData(spell).level and mana() >= if (ignoreCd or not getSpellCoolDown(spell)) and
getSpellData(spell).mana) then (ignoreRL or level() >= getSpellData(spell).level and mana() >=
return true getSpellData(spell).mana) then
else return true
return false else
return false
end
end end
-- if no data nor spell table then return true
return true
end end
-- exctracts data about spell from gamelib SpellInfo table -- exctracts data about spell from gamelib SpellInfo table
@ -269,17 +279,23 @@ end
-- global var to indicate that player is trying to do something -- global var to indicate that player is trying to do something
-- prevents action blocking by scripts -- prevents action blocking by scripts
-- below callbacks are triggers to changing the var state -- below callbacks are triggers to changing the var state
local isUsingTime = now
storage.isUsing = false storage.isUsing = false
macro(100, function()
storage.isUsing = now < isUsingTime and true or false
end)
onUse(function(pos, itemId, stackPos, subType) onUse(function(pos, itemId, stackPos, subType)
if pos.x < 65000 then storage.isUsing = true end if pos.x > 65000 then return end
schedule(1500, local tile = g_map.getTile(pos)
function() if storage.isUsing then storage.isUsing = false end end) if not tile then return end
local topThing = tile:getTopUseThing()
if topThing:isContainer() then return end
isUsingTime = now + 1000
end) end)
onUseWith(function(pos, itemId, target, subType) onUseWith(function(pos, itemId, target, subType)
if itemId ~= 3180 then return end if pos.x < 65000 then isUsingTime = now + 1000 end
if pos.x < 65000 then storage.isUsing = true end
schedule(1500,
function() if storage.isUsing then storage.isUsing = false end end)
end) end)
-- returns first word in string -- returns first word in string
@ -293,23 +309,21 @@ end
-- if exected then adds name or name and creature to tables -- if exected then adds name or name and creature to tables
-- returns boolean -- returns boolean
CachedFriends = {} CachedFriends = {}
CachedNeutrals = {}
CachedEnemies = {} CachedEnemies = {}
function isFriend(c) function isFriend(c)
local name = c local name = c
if type(c) ~= "string" then if type(c) ~= "string" then
if c == player then return true end if c == player then return true end
name = c:getName() name = c:getName()
if name == name() then return true end
end end
if CachedFriends[c] then return true end if CachedFriends[c] then return true end
if CachedNeutrals[c] or CachedEnemies[c] then return false end if CachedEnemies[c] then return false end
if table.find(storage.playerList.friendList, name) then if table.find(storage.playerList.friendList, name) then
CachedFriends[c] = true CachedFriends[c] = true
return true return true
elseif string.find(storage.serverMembers or "", name) then elseif BotServerMembers[name] ~= nil then
CachedFriends[c] = true CachedFriends[c] = true
return true return true
elseif storage.playerList.groupMembers then elseif storage.playerList.groupMembers then
@ -323,17 +337,9 @@ function isFriend(c)
CachedFriends[c] = true CachedFriends[c] = true
CachedFriends[p] = true CachedFriends[p] = true
return true return true
else
CachedNeutrals[c] = true
CachedNeutrals[p] = true
return false
end end
end end
else else
CachedNeutrals[c] = true
if c ~= p and p then
CachedNeutrals[p] = true
end
return false return false
end end
end end

View File

@ -88,6 +88,7 @@ context.findAllPaths = function(start, maxDist, params)
ignoreCost ignoreCost
allowUnseen allowUnseen
allowOnlyVisibleTiles allowOnlyVisibleTiles
maxDistanceFrom
]]-- ]]--
if type(params) ~= 'table' then if type(params) ~= 'table' then
params = {} params = {}
@ -99,6 +100,15 @@ context.findAllPaths = function(start, maxDist, params)
params[key] = 1 params[key] = 1
end end
end end
if type(params['maxDistanceFrom']) == 'table' then
if #params['maxDistanceFrom'] == 2 then
params['maxDistanceFrom'] = params['maxDistanceFrom'][1].x .. "," .. params['maxDistanceFrom'][1].y ..
"," .. params['maxDistanceFrom'][1].z .. "," .. params['maxDistanceFrom'][2]
elseif #params['maxDistanceFrom'] == 4 then
params['maxDistanceFrom'] = params['maxDistanceFrom'][1] .. "," .. params['maxDistanceFrom'][2] ..
"," .. params['maxDistanceFrom'][3] .. "," .. params['maxDistanceFrom'][4]
end
end
return g_map.findEveryPath(start, maxDist, params) return g_map.findEveryPath(start, maxDist, params)
end end
context.findEveryPath = context.findAllPaths context.findEveryPath = context.findAllPaths
@ -145,6 +155,7 @@ context.findPath = function(startPos, destPos, maxDist, params)
precision precision
marginMin marginMin
marginMax marginMax
maxDistanceFrom
]]-- ]]--
if not destPos or startPos.z ~= destPos.z then if not destPos or startPos.z ~= destPos.z then
return return

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.