Passer au contenu principal

Enums & Constants

TeamEnum (Target types for addSpell)

ValueNameDescription
0EnemyAny enemy
1AllyAny ally
2SelfSelf only
3EnemyAdjacentAdjacent enemy
4AllyAdjacentAdjacent ally
5SelfAdjacentSelf if adjacent
6EnemySummonEnemy summons only
7EnemyNotSummonEnemy non-summons
8AllySummonAlly summons
9AllyNotSummonAlly non-summons
10EnemySummonAdjacentAdjacent enemy summon
11EnemyNotSummonAdjacentAdjacent enemy non-summon
12AllySummonAdjacentAdjacent ally summon
13AllyNotSummonAdjacentAdjacent ally non-summon
-- Pass the integer value
-- Example: fightBasic:addSpell(8139, 0, 1, 2, false, 100)
--                                     ^--- 0 = Enemy

TacticEnum (playTurn tactic)

ValueNameDescription
0ImobileStay in place, cast from current cell
1HandToHandMove to melee range, then cast
2DistanceStay at range, cast from afar
3NoActionSkip all turns
4AdvancedBuilt-in advanced AI
5AdvancedInScriptLua script handles fight via callbacks
fightBasic:playTurn(1)  -- HandToHand
fightBasic:playTurn(2)  -- Distance

BreedEnum (Character class IDs)

ValueName
1Feca
2Osamodas
3Enutrof
4Sram
5Xelor
6Ecaflip
7Eniripsa
8Iop
9Cra
10Sadida
11Sacrieur
12Pandawa
13Rogue
14Masqueraider
15Steamer (Foggernaut)
local breed = fightCharacter:getBreed()  -- returns int 1-15

Default Attack Spells by Breed

ATTACK_SPELLS = {
    ["1"]  = 3,      -- Feca
    ["2"]  = 4714,   -- Osamodas
    ["3"]  = 43,     -- Enutrof
    ["4"]  = 61,     -- Sram
    ["5"]  = 7359,   -- Xelor
    ["6"]  = 7467,   -- Ecaflip
    ["7"]  = 4947,   -- Eniripsa
    ["8"]  = 8139,   -- Iop (Pression)
    ["9"]  = 5813,   -- Cra (Fleche de Transfusion)
    ["10"] = 183,    -- Sadida
    ["11"] = 5885,   -- Sacrieur
    ["12"] = 0,      -- Pandawa (0 = no spell, use raw melee)
    ["13"] = 2794,   -- Rogue
    ["14"] = 6131,   -- Masqueraider
    ["15"] = 3210,   -- Steamer
}

DirectionEnum

ValueName
0RIGHT
1DOWN_RIGHT
2DOWN
3DOWN_LEFT
4LEFT
5UP_LEFT
6UP
7UP_RIGHT

StatEnum

ValueNameDescription
-1NONENo stat
10STRENGHTEarth / Strength
11VITALITYVitality
12WISDOMWisdom
13CHANCEWater
14AGILITYAir
15INTELFire / Intelligence

Entity Model (Fight Entity Object)

Returned by fightAction:getAllEntities() and fightSlave:entity().
FieldTypeDescription
Teambooleantrue = ally, false = enemy
LifePointsintCurrent HP
MaxLifePointsintMax HP
CellIdintCurrent cell position
CreatureGenericIdintMonster/creature template ID
APintCurrent Action Points
MPintCurrent Movement Points
LevelintEntity level
PercentTerreintEarth resistance %
PercentFeuintFire resistance %
PercentEauintWater resistance %
PercentAirintAir resistance %
PercentNeutreintNeutral resistance %
Mycharacterbooleantrue = this is our bot character
IddoubleContextual entity ID
lancesortcellidintCell from which last spell was cast
gradeintEntity grade/rank
local entities = fightAction:getAllEntities()
for _, entity in ipairs(entities) do
    fightDebug:print("Name: " .. (entity["name"] or "?"))
    fightDebug:print("Cell: " .. entity["CellId"])
    fightDebug:print("HP: " .. entity["LifePoints"] .. "/" .. entity["MaxLifePoints"])
    fightDebug:print("Team: " .. tostring(entity["Team"]))  -- true=ally
    fightDebug:print("AP: " .. entity["AP"] .. " MP: " .. entity["MP"])
    fightDebug:print("Resistances: T=" .. entity["PercentTerre"]
        .. " F=" .. entity["PercentFeu"]
        .. " E=" .. entity["PercentEau"]
        .. " A=" .. entity["PercentAir"]
        .. " N=" .. entity["PercentNeutre"])
end

Error Codes (canCastSpellOnCell / canCastSpellOnCellAfterMove)

CodeMeaning
0NONE (Success — can cast)
1-16Various spell restrictions (range, AP cost, cooldown, line of sight, occupied cell, etc.)
Specific error code meanings are not documented in the binary. Test with canCastSpellOnCell and check the return value.

Lua Callbacks

When Tactic is set to AdvancedInScript, the bot calls these Lua functions:

fightManagementPosition(challengers, defenders)

Called once at fight start during the placement phase.
ParameterTypeDescription
challengerstable{[cellId] = entityId} — Your team’s placement cells. -1 = empty cell
defenderstable{[cellId] = entityId} — Enemy team’s placement cells
function fightManagementPosition(challengers, defenders)
    -- Pick the first free challenger cell
    for cell, id in pairs(challengers) do
        if id == -1 then
            fightAction:chooseCell(cell)
            break
        end
    end
end

fightManagement()

Called each turn when it’s any entity’s turn (including enemies/summons). You must check isItMyTurn().
function fightManagement()
    if fightCharacter:isItMyTurn() == true then
        -- Your turn logic here
    end
end

Complete Examples

Example 1: Generic Melee Fighter (any breed)

ATTACK_SPELLS = {
    ["1"]  = 3,      ["2"]  = 4714,  ["3"]  = 43,
    ["4"]  = 61,     ["5"]  = 7359,  ["6"]  = 7467,
    ["7"]  = 4947,   ["8"]  = 8139,  ["9"]  = 5813,
    ["10"] = 183,    ["11"] = 5885,  ["12"] = 7041,
    ["13"] = 2794,   ["14"] = 6131,  ["15"] = 3210,
}

function fightManagementPosition(challengers, defenders)
    global:delay(global:random(500, 1000))
    for cell, id in pairs(challengers) do
        if id == -1 then
            fightAction:chooseCell(cell)
            break
        end
    end
end

function fightManagement()
    if fightCharacter:isItMyTurn() == true then
        local myCell = fightCharacter:getCellId()
        local enemyCell = fightAction:getNearestEnemy()
        local spellId = ATTACK_SPELLS[tostring(character:breed())]

        -- Move toward enemy if not in range
        if fightAction:getDistance(myCell, enemyCell) > 1 then
            fightAction:moveTowardCell(enemyCell)
            fightDebug:delay(global:random(300, 600))
        end

        -- Cast spell up to 3 times (refresh enemy position each time)
        for i = 1, 3 do
            enemyCell = fightAction:getNearestEnemy()
            myCell = fightCharacter:getCellId()
            if spellId ~= 0 and fightAction:canCastSpellOnCell(myCell, spellId, enemyCell) == 0 then
                fightAction:castSpellOnCell(spellId, enemyCell)
                fightDebug:delay(global:random(200, 500))
            end
        end
    end
end

Example 2: Ranged Cra with Kiting

function fightManagement()
    if fightCharacter:isItMyTurn() ~= true then return end

    local myCell = fightCharacter:getCellId()
    local enemyCell = fightAction:getNearestEnemy()
    local dist = fightAction:getDistance(myCell, enemyCell)

    fightDebug:print("Turn " .. fightAction:getCurrentTurn()
        .. " | Dist=" .. dist
        .. " | AP=" .. fightCharacter:getAP()
        .. " | MP=" .. fightCharacter:getMP())

    -- Cast ranged spells first (Fleche de Transfusion)
    for i = 1, 2 do
        enemyCell = fightAction:getNearestEnemy()
        myCell = fightCharacter:getCellId()
        if fightAction:canCastSpellOnCell(myCell, 5813, enemyCell) == 0 then
            fightAction:castSpellOnCell(5813, enemyCell)
            fightDebug:delay(global:random(300, 600))
        end
    end

    -- Kite: if enemy is too close, move away
    if dist <= 2 and fightCharacter:getMP() > 0 then
        local cells = fightAction:getRealReachableCells()
        local bestCell = nil
        local bestDist = 0
        for _, cell in ipairs(cells) do
            local d = fightAction:getDistance(cell, enemyCell)
            if d > bestDist then
                bestDist = d
                bestCell = cell
            end
        end
        if bestCell and bestDist > dist then
            fightAction:moveTowardCell(bestCell)
            fightDebug:delay(global:random(200, 400))
        end
    end
end

Example 3: Eniripsa Healer + Summon Control

function fightManagement()
    if fightCharacter:isItMyTurn() ~= true then return end

    local myCell = fightCharacter:getCellId()

    -- Priority 1: Self-heal if HP < 60%
    if fightCharacter:getLifePointsP() < 60 then
        if fightAction:canCastSpellOnCell(myCell, 4947, myCell) == 0 then
            fightAction:castSpellOnCell(4947, myCell)
            fightDebug:delay(global:random(400, 700))
        end
    end

    -- Priority 2: Heal low-HP allies
    local entities = fightAction:getAllEntities()
    for _, e in ipairs(entities) do
        if e["Team"] == true and e["Mycharacter"] == false then
            local hpPercent = (e["LifePoints"] / e["MaxLifePoints"]) * 100
            if hpPercent < 50 then
                if fightAction:canCastSpellOnCell(myCell, 4947, e["CellId"]) == 0 then
                    fightAction:castSpellOnCell(4947, e["CellId"])
                    fightDebug:delay(global:random(300, 600))
                end
            end
        end
    end

    -- Priority 3: Attack nearest enemy with remaining AP
    local enemyCell = fightAction:getNearestEnemy()
    if fightAction:canCastSpellOnCell(myCell, 4947, enemyCell) == 0 then
        fightAction:castSpellOnCell(4947, enemyCell)
    end
end

Example 4: Using fightBasic for Simple AI

-- Setup spell rotation once (outside fight callback)
fightBasic:clearSpells()
fightBasic:addSpell(8131, 0, 1, 1, false, 100)  -- Epee Divine, Enemy, every turn, 1x
fightBasic:addSpell(8139, 0, 1, 2, false, 100)  -- Pression, Enemy, every turn, 2x
fightBasic:setFightSpeed(1)                       -- Ultra-Safe delays
fightBasic:setApproachDistance(0)                  -- No min distance (melee)

function fightManagement()
    if fightCharacter:isItMyTurn() == true then
        fightBasic:playTurn(1)  -- Let basic AI handle it (HandToHand)
    end
end

Example 5: Anti-Ban Delays Pattern

function fightManagement()
    if fightCharacter:isItMyTurn() ~= true then return end

    -- Human-like delay before starting turn
    fightDebug:delay(global:random(800, 1500))

    local myCell = fightCharacter:getCellId()
    local enemyCell = fightAction:getNearestEnemy()

    -- Move with delay
    if fightAction:getDistance(myCell, enemyCell) > 1 then
        fightAction:moveTowardCell(enemyCell)
        fightDebug:delay(global:random(400, 900))  -- wait after move
    end

    -- Cast with delay between each spell
    for i = 1, 3 do
        enemyCell = fightAction:getNearestEnemy()
        myCell = fightCharacter:getCellId()
        if fightAction:canCastSpellOnCell(myCell, 8139, enemyCell) == 0 then
            fightAction:castSpellOnCell(8139, enemyCell)
            fightDebug:delay(global:random(300, 700))  -- delay between casts
        end
    end

    -- End-of-turn delay (simulates thinking)
    fightDebug:delay(global:random(200, 500))
end

function fightManagementPosition(challengers, defenders)
    -- Delay before placing (humans don't instant-place)
    global:delay(global:random(1000, 2000))
    for cell, id in pairs(challengers) do
        if id == -1 then
            fightAction:chooseCell(cell)
            break
        end
    end
end

Sous-pages

Combat basique

Méthodes de combat basiques : playTurn, setFightSpeed et fonctions principales.

Actions de combat

Lancement de sorts, déplacement, pathfinding et gestion des entités.

Personnage de combat

Stats et informations du personnage en combat.

Debug de combat

Débogage et journalisation des informations de combat.

Défis de combat

Gestion des défis de combat.