> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dotouch-emu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Combat - Vue d'ensemble

> Vue d'ensemble de toutes les méthodes de combat, énumérations et modèles d'entités pour l'automatisation des combats dans dotouch-emu.

## Enums & Constants

### TeamEnum (Target types for addSpell)

| Value | Name                   | Description               |
| ----- | ---------------------- | ------------------------- |
| `0`   | Enemy                  | Any enemy                 |
| `1`   | Ally                   | Any ally                  |
| `2`   | Self                   | Self only                 |
| `3`   | EnemyAdjacent          | Adjacent enemy            |
| `4`   | AllyAdjacent           | Adjacent ally             |
| `5`   | SelfAdjacent           | Self if adjacent          |
| `6`   | EnemySummon            | Enemy summons only        |
| `7`   | EnemyNotSummon         | Enemy non-summons         |
| `8`   | AllySummon             | Ally summons              |
| `9`   | AllyNotSummon          | Ally non-summons          |
| `10`  | EnemySummonAdjacent    | Adjacent enemy summon     |
| `11`  | EnemyNotSummonAdjacent | Adjacent enemy non-summon |
| `12`  | AllySummonAdjacent     | Adjacent ally summon      |
| `13`  | AllyNotSummonAdjacent  | Adjacent ally non-summon  |

<CodeGroup>
  ```lua Usage theme={null}
  -- Pass the integer value
  -- Example: fightBasic:addSpell(8139, 0, 1, 2, false, 100)
  --                                     ^--- 0 = Enemy
  ```
</CodeGroup>

***

### TacticEnum (playTurn tactic)

| Value | Name             | Description                            |
| ----- | ---------------- | -------------------------------------- |
| `0`   | Imobile          | Stay in place, cast from current cell  |
| `1`   | HandToHand       | Move to melee range, then cast         |
| `2`   | Distance         | Stay at range, cast from afar          |
| `3`   | NoAction         | Skip all turns                         |
| `4`   | Advanced         | Built-in advanced AI                   |
| `5`   | AdvancedInScript | Lua script handles fight via callbacks |

<CodeGroup>
  ```lua Usage theme={null}
  fightBasic:playTurn(1)  -- HandToHand
  fightBasic:playTurn(2)  -- Distance
  ```
</CodeGroup>

***

### BreedEnum (Character class IDs)

| Value | Name                 |
| ----- | -------------------- |
| `1`   | Feca                 |
| `2`   | Osamodas             |
| `3`   | Enutrof              |
| `4`   | Sram                 |
| `5`   | Xelor                |
| `6`   | Ecaflip              |
| `7`   | Eniripsa             |
| `8`   | Iop                  |
| `9`   | Cra                  |
| `10`  | Sadida               |
| `11`  | Sacrieur             |
| `12`  | Pandawa              |
| `13`  | Rogue                |
| `14`  | Masqueraider         |
| `15`  | Steamer (Foggernaut) |

<CodeGroup>
  ```lua Usage theme={null}
  local breed = fightCharacter:getBreed()  -- returns int 1-15
  ```
</CodeGroup>

***

### Default Attack Spells by Breed

<CodeGroup>
  ```lua Spell Table theme={null}
  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
  }
  ```
</CodeGroup>

***

### DirectionEnum

| Value | Name        |
| ----- | ----------- |
| `0`   | RIGHT       |
| `1`   | DOWN\_RIGHT |
| `2`   | DOWN        |
| `3`   | DOWN\_LEFT  |
| `4`   | LEFT        |
| `5`   | UP\_LEFT    |
| `6`   | UP          |
| `7`   | UP\_RIGHT   |

***

### StatEnum

| Value | Name     | Description         |
| ----- | -------- | ------------------- |
| `-1`  | NONE     | No stat             |
| `10`  | STRENGHT | Earth / Strength    |
| `11`  | VITALITY | Vitality            |
| `12`  | WISDOM   | Wisdom              |
| `13`  | CHANCE   | Water               |
| `14`  | AGILITY  | Air                 |
| `15`  | INTEL    | Fire / Intelligence |

***

## Entity Model (Fight Entity Object)

Returned by `fightAction:getAllEntities()` and `fightSlave:entity()`.

| Field               | Type    | Description                         |
| ------------------- | ------- | ----------------------------------- |
| `Team`              | boolean | `true` = ally, `false` = enemy      |
| `LifePoints`        | int     | Current HP                          |
| `MaxLifePoints`     | int     | Max HP                              |
| `CellId`            | int     | Current cell position               |
| `CreatureGenericId` | int     | Monster/creature template ID        |
| `AP`                | int     | Current Action Points               |
| `MP`                | int     | Current Movement Points             |
| `Level`             | int     | Entity level                        |
| `PercentTerre`      | int     | Earth resistance %                  |
| `PercentFeu`        | int     | Fire resistance %                   |
| `PercentEau`        | int     | Water resistance %                  |
| `PercentAir`        | int     | Air resistance %                    |
| `PercentNeutre`     | int     | Neutral resistance %                |
| `Mycharacter`       | boolean | `true` = this is our bot character  |
| `Id`                | double  | Contextual entity ID                |
| `lancesortcellid`   | int     | Cell from which last spell was cast |
| `grade`             | int     | Entity grade/rank                   |

<CodeGroup>
  ```lua Iterating entities theme={null}
  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
  ```
</CodeGroup>

***

## Error Codes (canCastSpellOnCell / canCastSpellOnCellAfterMove)

| Code   | Meaning                                                                                   |
| ------ | ----------------------------------------------------------------------------------------- |
| `0`    | NONE (Success -- can cast)                                                                |
| `1-16` | Various spell restrictions (range, AP cost, cooldown, line of sight, occupied cell, etc.) |

<Note>
  Specific error code meanings are not documented in the binary. Test with `canCastSpellOnCell` and check the return value.
</Note>

***

## 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.

| Parameter     | Type  | Description                                                               |
| ------------- | ----- | ------------------------------------------------------------------------- |
| `challengers` | table | `{[cellId] = entityId}` -- Your team's placement cells. `-1` = empty cell |
| `defenders`   | table | `{[cellId] = entityId}` -- Enemy team's placement cells                   |

<CodeGroup>
  ```lua Basic placement theme={null}
  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
  ```

  ```lua Advanced placement (closest to enemy) theme={null}
  function fightManagementPosition(challengers, defenders)
      global:delay(global:random(500, 1000))
      local bestCell = nil
      local bestDist = 999

      -- Find nearest enemy cell
      local enemyCell = nil
      for cell, _ in pairs(defenders) do
          enemyCell = cell
          break
      end

      -- Pick closest free challenger cell to enemy
      for cell, id in pairs(challengers) do
          if id == -1 and enemyCell then
              local dist = fightAction:getDistance(cell, enemyCell)
              if dist < bestDist then
                  bestDist = dist
                  bestCell = cell
              end
          end
      end

      if bestCell then
          fightAction:chooseCell(bestCell)
      end
  end
  ```
</CodeGroup>

***

### fightManagement()

Called **each turn** when it's any entity's turn (including enemies/summons). You **must** check `isItMyTurn()`.

<CodeGroup>
  ```lua Template theme={null}
  function fightManagement()
      if fightCharacter:isItMyTurn() == true then
          -- Your turn logic here
      end
  end
  ```
</CodeGroup>

***

## Complete Examples

### Example 1: Generic Melee Fighter (any breed)

<CodeGroup>
  ```lua Generic Melee theme={null}
  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
  ```
</CodeGroup>

***

### Example 2: Ranged Cra with Kiting

<CodeGroup>
  ```lua Cra Kiting theme={null}
  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
  ```
</CodeGroup>

***

### Example 3: Eniripsa Healer + Summon Control

<CodeGroup>
  ```lua Eniripsa Healer theme={null}
  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
  ```
</CodeGroup>

***

### Example 4: Using fightBasic for Simple AI

<CodeGroup>
  ```lua Basic AI Setup theme={null}
  -- 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
  ```
</CodeGroup>

***

### Example 5: Anti-Ban Delays Pattern

<CodeGroup>
  ```lua Anti-Ban Delays theme={null}
  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
  ```
</CodeGroup>

***

## Sous-pages

<CardGroup cols={2}>
  <Card title="Combat basique" icon="sword" href="/methodes/combat/basique">
    Méthodes de combat basiques : playTurn, setFightSpeed et fonctions principales.
  </Card>

  <Card title="Actions de combat" icon="bolt" href="/methodes/combat/actions">
    Lancement de sorts, déplacement, pathfinding et gestion des entités.
  </Card>

  <Card title="Personnage de combat" icon="user-shield" href="/methodes/combat/personnage">
    Stats et informations du personnage en combat.
  </Card>

  <Card title="Debug de combat" icon="bug" href="/methodes/combat/debug">
    Débogage et journalisation des informations de combat.
  </Card>

  <Card title="Défis de combat" icon="trophy" href="/methodes/combat/defi">
    Gestion des défis de combat.
  </Card>
</CardGroup>
