691 lines
17 KiB
Lua

-- if you want to change tab, in line below insert: setDefaultTab("tab name")
attackPanelName = "attackbot"
local ui = setupUI([[
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: mode
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.horizontalCenter
text: Mode: PVP
margin-right: 2
margin-top: 4
font: cipsoftFont
height: 17
Button
id: safe
anchors.top: settings.bottom
anchors.left: parent.horizontalCenter
anchors.right: parent.right
text: PVP Safe
margin-left: 2
margin-top: 4
height: 17
font:cipsoftFont
]])
ui:setId(attackPanelName)
local i = 1
local j = 1
local k = 1
local pvpDedicated = false
local item = false
UI.Separator()
if not storage[attackPanelName] or not storage[attackPanelName].attackTable then
storage[attackPanelName] = {
pvpMode = false,
pvpSafe = true,
enabled = false,
attackTable = {}
}
end
local categories = {
"Select Category",
"Area Spell (exevo mas san, exevo gran mas flam etc.)",
"Adjacent (exori, exori gran)",
"Front Sweep (exori min)",
"Wave (exevo tera hur, exevo gran vis lux)",
"Targeted Spell (exori ico, exori flam etc.)",
"Targeted Rune (sudden death, heavy magic missle etc.)",
"Area Rune (great fireball, avalanche etc.)"
}
local labels = {
"",
"Area Spell",
"Adjacent",
"Front Sweep",
"Wave",
"Targeted Spell",
"Targeted Rune",
"Area Rune",
}
local range = {
"Select Range",
"Range: 1",
"Range: 2",
"Range: 3",
"Range: 4",
"Range: 5",
"Range: 6",
"Range: 7",
"Range: 8",
"Range: 9"
}
local pattern = {
"Pattern",
"Single (exori frigo, SD)",
"Large AOE (mas tera)",
"Medium AOE (mas frigo)",
"Small AOE (mas san)",
"Large Wave (tera hur)",
"Medium Wave (frigo hur)",
"Small Wave (gran frigo hur)",
"Beam (exevo vis lux)",
"Adjacent (exori)",
"Area Rune (GFB, AVA)"
}
local updateModeText = function()
local text
if storage[attackPanelName].pvpMode then
text = "PVP"
ui.mode:setColor("yellow")
else
text = "HUNT"
ui.mode:setColor("green")
end
ui.mode:setText("MODE: " .. text)
end
updateModeText()
local updatePvpColor = function()
if storage[attackPanelName].pvpSafe then
ui.safe:setColor("green")
else
ui.safe:setColor("white")
end
end
updatePvpColor()
ui.title:setOn(storage[attackPanelName].enabled)
ui.title.onClick = function(widget)
storage[attackPanelName].enabled = not storage[attackPanelName].enabled
widget:setOn(storage[attackPanelName].enabled)
end
ui.mode.onClick = function(widget)
storage[attackPanelName].pvpMode = not storage[attackPanelName].pvpMode
updateModeText()
end
ui.safe.onClick = function(widget)
storage[attackPanelName].pvpSafe = not storage[attackPanelName].pvpSafe
updatePvpColor()
end
ui.settings.onClick = function(widget)
attackWindow:show()
attackWindow:raise()
attackWindow:focus()
end
rootWidget = g_ui.getRootWidget()
if rootWidget then
attackWindow = g_ui.createWidget('AttackWindow', rootWidget)
attackWindow:hide()
-- functions
local updateCategoryText = function()
attackWindow.category:setText(categories[i])
end
updateCategoryText()
local updateParameter1Text = function()
attackWindow.parameter1:setText(pattern[k])
end
updateParameter1Text()
local updateParameter2Text = function()
attackWindow.parameter2:setText(range[j])
end
updateParameter2Text()
-- checkbox
attackWindow.pvpSpell.onClick = function(widget)
pvpDedicated = not pvpDedicated
attackWindow.pvpSpell:setChecked(pvpDedicated)
end
--buttons
attackWindow.CloseButton.onClick = function(widget)
attackWindow:hide()
end
local inputTypeToggle = function()
if attackWindow.category:getText():lower():find("rune") then
item = true
attackWindow.spellFormula:setText("")
attackWindow.spellFormula:hide()
attackWindow.spellDescription:hide()
attackWindow.itemId:show()
attackWindow.itemDescription:show()
else
item = false
attackWindow.itemId:setItemId(0)
attackWindow.itemId:hide()
attackWindow.itemDescription:hide()
attackWindow.spellFormula:show()
attackWindow.spellDescription:show()
end
end
inputTypeToggle()
attackWindow.categoryNext.onClick = function(widget)
if i == #categories then
i = 1
else
i = i + 1
end
updateCategoryText()
inputTypeToggle()
end
attackWindow.categoryPrev.onClick = function(widget)
if i == 1 then
i = #categories
else
i = i - 1
end
updateCategoryText()
inputTypeToggle()
end
attackWindow.parameter1Next.onClick = function(widget)
if k == #pattern then
k = 1
else
k = k + 1
end
updateParameter1Text()
end
attackWindow.parameter1Prev.onClick = function(widget)
if k == 1 then
k = #pattern
else
k = k - 1
end
updateParameter1Text()
end
attackWindow.parameter2Next.onClick = function(widget)
if j == #range then
j = 1
else
j = j + 1
end
updateParameter2Text()
end
attackWindow.parameter2Prev.onClick = function(widget)
if j == 1 then
j = #range
else
j = j - 1
end
updateParameter2Text()
end
local validVal = function(v)
if type(v) ~= "number" then
local val = tonumber(v)
if not val then return false end
end
if v >= 0 and v < 101 then
return true
else
return false
end
end
local clearValues = function()
attackWindow.spellFormula:setText("")
attackWindow.minMana:setText("")
attackWindow.minMonsters:setText("")
attackWindow.itemId:setItemId(0)
pvpDedicated = false
item = false
attackWindow.pvpSpell:setChecked(false)
i = 1
j = 1
k = 1
updateParameter1Text()
updateParameter2Text()
updateCategoryText()
inputTypeToggle()
end
attackWindow.addButton.onClick = function(widget)
local val
if (item and attackWindow.itemId:getItemId() <= 100) or (not item and attackWindow.spellFormula:getText():len() == 0) then
warn("AttackBot: missing spell or item id!")
elseif not tonumber(attackWindow.minMana:getText()) or not validVal(tonumber(attackWindow.minMana:getText())) then
warn("AttackBot: Mana Values incorrect! it has to be number from between 1 and 100")
elseif not tonumber(attackWindow.minMonsters:getText()) or not validVal(tonumber(attackWindow.minMonsters:getText())) then
warn("AttackBot: Monsters Count incorrect! it has to be number higher than 0")
elseif i == 1 or j == 1 or k == 1 then
warn("AttackBot: Categories not changed! You need to be more precise")
else
if item then
val = attackWindow.itemId:getItemId()
else
val = attackWindow.spellFormula:getText()
end
local pvpText
table.insert(storage[attackPanelName].attackTable, {attack = val, manaCost = tonumber(attackWindow.minMana:getText()), minMonsters = tonumber(attackWindow.minMonsters:getText()), pvp = pvpDedicated, dist = j-1, model = k, category = i})
local label = g_ui.createWidget("AttackEntry", attackWindow.attackList)
if pvpDedicated then
label:setText("(" .. tonumber(attackWindow.minMana:getText()) .. "% MP) " .. labels[i] .. ": " .. val .. " (Range: ".. j-1 .. ")")
label:setColor("yellow")
else
label:setText("(" .. tonumber(attackWindow.minMana:getText()) .. "% MP & mob >= " .. tonumber(attackWindow.minMonsters:getText()) .. ") " .. labels[i] .. ": " .. val .. " (Range: ".. j-1 .. ")")
label:setColor("green")
end
clearValues()
end
end
if storage[attackPanelName].attackTable and #storage[attackPanelName].attackTable > 0 then
for _, entry in pairs(storage[attackPanelName].attackTable) do
local label = g_ui.createWidget("AttackEntry", attackWindow.attackList)
label.remove.onClick = function(widget)
table.removevalue(storage[attackPanelName].attackTable, entry)
label:destroy()
end
if entry.pvp then
label:setText("(" .. entry.manaCost .. "% MP) " .. labels[entry.category] .. ": " .. entry.attack .. " (Range: ".. j-1 .. ")")
label:setColor("yellow")
else
label:setText("(" .. entry.manaCost .. "% MP & mob >= " .. entry.minMonsters .. ") " .. labels[entry.category] .. ": " .. entry.attack .. " (Range: ".. j-1 .. ")")
label:setColor("green")
end
end
end
end
-- executor
-- table example (attack = 3155, manaCost = 50(%), minMonsters = 5, pvp = true, dist = 3, model = 6, category = 3)
-- i = category
-- j = range
-- k = pattern - covered
local patterns = {
"",
[[
0000001000000
0000011100000
0000111110000
0001111111000
0011111111100
0111111111110
1111111111111
0111111111110
0011111111100
0001111111000
0000111110000
0000011100000
0000001000000
]],
[[
00000100000
00011111000
00111111100
01111111110
01111111110
11111111111
01111111110
01111111110
00111111100
00001110000
00000100000
]],
[[
0011100
0111110
1111111
1111111
1111111
0111110
0011100
]],
[[
0000NNN0000
0000NNN0000
0000NNN0000
00000N00000
WWW00N00EEE
WWWWW0EEEEE
WWW00S00EEE
00000S00000
0000SSS0000
0000SSS0000
0000SSS0000
]],
[[
000NNNNN000
000NNNNN000
0000NNN0000
WW00NNN00EE
WWWW0N0EEEE
WWWWW0EEEEE
WWWW0S0EEEE
WW00SSS00EE
0000SSS0000
000SSSSS000
000SSSSS000
]],
[[
00NNN00
00NNN00
WW0N0EE
WWW0EEE
WW0S0EE
00SSS00
00SSS00
]],
[[
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
WWWWWWW0EEEEEEE
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
]],
"",
""
}
local safePatterns = {
"",
[[
000000010000000
000000111000000
000001111100000
000011111110000
000111111111000
001111111111100
011111111111110
111111111111111
011111111111110
001111111111100
000111111111000
000011111110000
000001111100000
000000111000000
000000010000000
]],
[[
0000011100000
0000111110000
0001111111000
0011111111100
0111111111110
0111111111110
1111111111111
0111111111110
0111111111110
0011111111100
0001111111000
0000111110000
0000011100000
]],
[[
000111000
001111100
011111110
111111111
111111111
111111111
011111110
001111100
000111000
]],
[[
0000NNNNN0000
0000NNNNN0000
0000NNNNN0000
0000NNNNN0000
WWWW0NNN0EEEE
WWWWWNNNEEEEE
WWWWWW0EEEEEE
WWWWWSSSEEEEE
WWWW0SSS0EEEE
0000SSSSS0000
0000SSSSS0000
0000SSSSS0000
0000SSSSS0000
]],
[[
000NNNNNNN000
000NNNNNNN000
000NNNNNNN000
WWWWNNNNNEEEE
WWWWNNNNNEEEE
WWWWWNNNEEEEE
WWWWWW0EEEEEE
WWWWWSSSEEEEE
WWWWSSSSSEEEE
WWWWSSSSSEEEE
000SSSSSSS000
000SSSSSSS000
000SSSSSSS000
]],
[[
00NNNNN00
00NNNNN00
WWNNNNNEE
WWWWNEEEE
WWWW0EEEE
WWWWSEEEE
WWSSSSSEE
00SSSSS00
00SSSSS00
]],
[[
0000000NNN0000000
0000000NNN0000000
0000000NNN0000000
0000000NNN0000000
0000000NNN0000000
0000000NNN0000000
0000000NNN0000000
WWWWWWWNNNEEEEEEE
WWWWWWWW0EEEEEEEE
WWWWWWWSSSEEEEEEE
0000000SSS0000000
0000000SSS0000000
0000000SSS0000000
0000000SSS0000000
0000000SSS0000000
0000000SSS0000000
0000000SSS0000000
]],
"",
""
}
local posN = [[
111
000
000
]]
local posE = [[
001
001
001
]]
local posS = [[
000
000
111
]]
local posW = [[
100
100
100
]]
macro(1000, function()
if not storage[attackPanelName].enabled then return end
if #storage[attackPanelName].attackTable == 0 or isInPz() or not target() or modules.game_cooldown.isGroupCooldownIconActive(1) or modules.game_cooldown.isGroupCooldownIconActive(4) then return end
local monstersN = 0
local monstersE = 0
local monstersS = 0
local monstersW = 0
monstersN = getCreaturesInArea(pos(), posN, 2)
monstersE = getCreaturesInArea(pos(), posE, 2)
monstersS = getCreaturesInArea(pos(), posS, 2)
monstersW = getCreaturesInArea(pos(), posN, 2)
local posTable = {monstersE, monstersN, monstersS, monstersW}
local bestSide = 0
local bestDir
-- pulling out the biggest number
for i, v in pairs(posTable) do
if v > bestSide then
bestSide = v
end
end
-- associate biggest number with turn direction
if monstersN == bestSide then bestDir = 0
elseif monstersE == bestSide then bestDir = 1
elseif monstersS == bestSide then bestDir = 2
elseif monstersW == bestSide then bestDir = 3
end
if player:getDirection() ~= bestDir and bestSide > 0 and CaveBot.isOn() then
turn(bestDir)
end
for _, entry in pairs(storage[attackPanelName].attackTable) do
if (type(entry.attack) == "string" and canCast(entry.attack)) or (type(entry.attack) == "number" and findItem(entry.attack)) then
if manapercent() >= entry.manaCost and distanceFromPlayer(target():getPosition()) <= entry.dist then
if storage[attackPanelName].pvpMode then
if entry.pvp and target():canShoot() then
if type(entry.attack) == "string" then
say(entry.attack)
return
else
if not storage.isUsing then
useWith(entry.attack, target())
return
end
end
end
else
if entry.category == 6 or entry.category == 7 then
if getMonsters(4) >= entry.minMonsters then
if type(entry.attack) == "number" then
if not storage.isUsing then
useWith(entry.attack, target())
return
end
else
say(entry.attack)
return
end
end
else
if killsToRs() > 2 then
local areaTile = getBestTileByPatern(patterns[4], 2, entry.dist, storage[attackPanelName].pvpSafe)
if entry.category == 4 and (not storage[attackPanelName].pvpSafe or isSafe(2, false)) and bestSide >= entry.minMonsters then
say(entry.attack)
return
elseif entry.category == 3 and (not storage[attackPanelName].pvpSafe or isSafe(2, false)) and getMonsters(1) >= entry.minMonsters then
say(entry.attack)
return
elseif entry.category == 5 and getCreaturesInArea(player, patterns[entry.model], 2) >= entry.minMonsters and (not storage[attackPanelName].pvpSafe or getCreaturesInArea(player, safePatterns[entry.model], 3) == 0) then
say(entry.attack)
return
elseif entry.category == 2 and getCreaturesInArea(pos(), patterns[entry.model], 2) >= entry.minMonsters and (not storage[attackPanelName].pvpSafe or getCreaturesInArea(pos(), safePatterns[entry.model], 3) == 0) then
say(entry.attack)
return
elseif entry.category == 8 and areaTile and areaTile.count >= entry.minMonsters then
if not storage.isUsing then
useWith(entry.attack, areaTile.pos:getTopUseThing())
end
return
else
if entry.category == 6 or entry.category == 7 then
if getMonsters(4) >= entry.minMonsters then
if type(entry.attack) == "number" then
if not storage.isUsing then
useWith(entry.attack, target())
return
end
else
say(entry.attack)
return
end
end
end
end
else
if entry.category == 6 or entry.category == 7 then
if getMonsters(4) >= entry.minMonsters then
if type(entry.attack) == "number" then
if not storage.isUsing then
useWith(entry.attack, target())
return
end
else
say(entry.attack)
return
end
end
end
end
end
end
end
end
end
end)