2021-04-09 19:01:18 +00:00

182 lines
6.8 KiB
Lua

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
if not storage.targetBotTargets then
storage.targetBotTargets = 0
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 then
if config.lureMin >= targets then
storage.TargetBotLure = true
elseif targets >= config.lureMax then
storage.TargetBotLure = false
end
end
storage.targetBotTargets = targets
storage.targetBotDynamicLureDelayValue = config.lureDelay
if not storage.targetBotLureMax then
storage.targetBotLureMax = 0
end
if config.lureMax then
storage.targetBotLureMax = config.lureMax
end
-- luring
if TargetBot.canLure() and (config.lure or config.lureCavebot or config.dynamicLure) and not (config.chase and creature:getHealthPercent() < 5) and not isTrapped then
local monsters = 0
if storage.TargetBotLure then
return TargetBot.allowCaveBot(150)
else
if targets < config.lureCount then
if config.lureCavebot then
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 config.chase and (creature:getHealthPercent() < 30 or not config.keepDistance) then
if #currentDistance > 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1})
end
elseif config.keepDistance then
if #currentDistance ~= config.keepDistanceRange and #currentDistance ~= config.keepDistanceRange + 1 then
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1})
end
end
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 storage.targetBotLureMax then return end
if storage.targetBotTargets < storage.targetBotLureMax/2 or not target() then return end
CaveBot.delay(storage.targetBotDynamicLureDelayValue or 0)
end)