Quote Originally Posted by Trykon View Post
Also xenobot is not good with runes, so I avoid making scripts using runes as much as possible
Never tried this (old)script but if you're into coding you might be able to use it as an outline to rewrite/edit/update most of the lines so that it functions better than the bot's rune shooter.


Code:
-- Attack magic including area runes.
-- By Tururu. V1.00
 
-- CONFIGURATION
-- Monsters for each attack
local SpellMonsters={"Lizard Dragon Priest","Lizard High Guard","Lizard Legionnaire","Lizard Zaogun","Killer Caiman","Eternal Guardians","Death Blob","Mutated Bat","Mutated Tiger"}
local AreaRuneMonsters={"Lizard Dragon Priest","Lizard High Guard","Lizard Legionnaire","Lizard Zaogun","Killer Caiman","Eternal Guardians","Death Blob","Mutated Bat","Mutated Tiger"}
local UltimateMonsters={"Demon Skeleton"}
-- Number of monsters for area rune and ultimate attack
local AreaRuneMin=3
local UltimateMin=5
-- Spells and runes to use
local SpellAttack = "exori Frigo"
local SpellRange = 3
local SpellMana = 20
local AreaRuneID = 3161 -- 3202 Thunderstorm
local UltimateAttack = "exori vis"
local UltimateMana = 20
 
local MaxRadius=3 --For search of suitable tiles to shoot runes, a radius around the center of gravity
-- END OF CONFIGURATION
 
local InsideAreaRune={
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
local ScoreAreaRune={
{2,2,2,1,0,0,0,0,0,0,0,0,0,0,0},
{2,2,2,1,0,0,0,0,0,0,0,0,0,0,0},
{2,2,1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
 
local AreaRuneN
local UltimateN
 
local RuneExhaust=0
 
local tx=0
local ty=0
local tz=0
local selfx
local selfy
 
 
function TrySpell()  --A function to use the default spell attack
    if(Self.CanCastSpell(SpellAttack))then
        --Get current target creature. Targeting handled by xenobot
        local target = Creature.GetByID(Self.TargetID())
 
        if(target:isValid() and target:isMonster())then
            if(target:isOnScreen(false) and target:isVisible() and target:isAlive())then
                for n in pairs(SpellMonsters) do
                    if(SpellMonsters[n]==target:Name()) then
                        if(target:DistanceFromSelf() <= SpellRange) then
                            Self.Cast(SpellAttack,SpellMana)
                        end
                        break
                    end
                end
            end
        end
    end
end
 
while(true) do
    --Get all creatures in my floor, alive, which are monsters
    local tbl = {} 
    for i = CREATURES_LOW, CREATURES_HIGH do
        local creature = Creature.GetFromIndex(i)
        if(creature:isValid() and creature:isMonster())then
            if(creature:isOnScreen(false) and creature:isVisible() and creature:isAlive())then
                table.insert(tbl, creature)
            end
        end
    end
 
    --Calculate number of creatures to use area rune/ultimate spell
    local MonsterX = {}
    local MonsterY = {}
    local AverageX=0
    local AverageY=0
    AreaRuneN=0
    UltimateN=0
    if(table.getn(tbl)>=AreaRuneMin) then
        for _, cid in ipairs(tbl) do
            for n in pairs(AreaRuneMonsters) do
                if(AreaRuneMonsters[n]==cid:Name()) then
                    AreaRuneN=AreaRuneN+1
                    MonsterX[AreaRuneN]= cid:Position().x
                    MonsterY[AreaRuneN]= cid:Position().y
                    AverageX=AverageX+MonsterX[AreaRuneN]
                    AverageY=AverageY+MonsterY[AreaRuneN]
                    break
                end
            end
            for n in pairs(UltimateMonsters) do
                if(UltimateMonsters[n]==cid:Name()) then
                    UltimateN=UltimateN+1
                    break
                end
            end
        end
    end
     
     
    if(UltimateN>=UltimateMin and Self.CanCastSpell(UltimateAttack))then --Many creatures on screen, cast ultimate spell
        Self.Cast(UltimateAttack,UltimateMana)
        wait(600)
    elseif(AreaRuneN>=AreaRuneMin and RuneExhaust<=0 and Self.ItemCount(AreaRuneID)>0) then --Enough creatures to shoot runes, search suitable tile to shoot area rune
        AverageX=math.floor(AverageX/AreaRuneN) -- Center of gravity of the creatures included in the area rune list. A good starting point to search
        AverageY=math.floor(AverageY/AreaRuneN)
        local SuitableTileFound=false
        local SuitableX
        local SuitableY
        local OnTileN=0
        local OnTileScore=0
        local MaxScore=0
        local MaxOnTile=0
        tz=Self.Position().z
        selfx=Self.Position().x
        selfy=Self.Position().y
        for tx=AverageX-MaxRadius,AverageX+MaxRadius do
            if(math.abs(tx-selfx)<=7) then   --Dont want to check tiles outside of the screen
                for ty=AverageY-MaxRadius,AverageY+MaxRadius do
                    if(math.abs(ty-selfy)<=5) then   --Dont want to check tiles outside of the screen
                        if( Map.IsTileWalkable(tx,ty,tz))then   --Can shoot only if walkable
                            OnTileN=0
                            OnTileScore=0
                            for i= 1, AreaRuneN do
                                --Checking whether the monster is inside the rune by checking against the array with the drawing of the area. Adding 1 to the indexes because lua starts in i=1
                                --Same for scores. Give more points to the inside of the area, to try to catch moving monsters.
                                if(InsideAreaRune[math.abs(ty-MonsterY[i])+1][math.abs(tx-MonsterX[i])+1]==1)then  
                                    OnTileN=OnTileN+1
                                    OnTileScore=OnTileScore+ScoreAreaRune[math.abs(ty-MonsterY[i])+1][math.abs(tx-MonsterX[i])+1]
                                end
                            end
 
                            if(OnTileN>=AreaRuneMin) then --Check that the position we just checked covers enough monsters to be worth a rune shot
                                SuitableTileFound=true
                                if(OnTileScore>MaxScore)then --Keep in memory the position with the best score
                                    SuitableX=tx
                                    SuitableY=ty
                                    MaxScore=OnTileScore
                                    MaxOnTile=OnTileN
                                end
                            end
                        end
                    end
                end
            end
        end
         
         
        if(SuitableTileFound)then --We found a place to shoot
            local AreaRunesLeft=Self.ItemCount(AreaRuneID)
            print("Found X:"..SuitableX.." Y:"..SuitableY.." to hit "..MaxOnTile.." monsters with score "..MaxScore..". Runes: "..AreaRunesLeft)
            delayWalker(400)
            Self.UseItemWithGround(AreaRuneID,SuitableX,SuitableY,Self.Position().z)
            wait(600)
            if(Self.ItemCount(AreaRuneID)<AreaRunesLeft)then --The exhaust for runes is 2 seconds. We already waited 600 ms, wait 1400 more if we are positive in this check that we shot a rune.
                print("Exhausted")
                RuneExhaust=1400
            end
        else
            TrySpell()
        end
    else -- Default situation, use normal spells
        TrySpell()
    end
 
    if(RuneExhaust>0)then
        RuneExhaust=RuneExhaust-200
    end
     
    wait(200)
end