<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="45">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"Reassign &lt;ID&gt;&lt;/ID&gt; serial number in .CT file"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Define Lua Script for reassigning IDs and creating backups
{$lua}
--NO_ACTIVATE
if syntaxcheck then return end
if memrec then print(memrec.Description) end
local function reassignIDs()
  -- Open file dialog
  local dialog = createOpenDialog()
  dialog.Title = "Select a .CT file"
  dialog.Filter = "Cheat Table Files (*.ct)|*.ct"

  if not dialog:execute() then
    print("No file selected, operation cancelled.")
    return
  end

  local filePath = dialog.FileName
  print("Selected file: " .. filePath)

  -- Create a backup of the original .CT file
  local backupPath = filePath .. ".bak"
  local originalFile = io.open(filePath, "r")
  if not originalFile then
    print("Failed to open the original file: " .. filePath)
    return
  end

  local originalContent = originalFile:read("*all")
  originalFile:close()

  local backupFile = io.open(backupPath, "w")
  if not backupFile then
    print("Failed to create backup file: " .. backupPath)
    return
  end

  backupFile:write(originalContent)
  backupFile:close()
  print("Backup created: " .. backupPath)

  -- Open original file for editing
  local idCounter = 0
  local newContent = originalContent:gsub("&lt;ID&gt;%d+&lt;/ID&gt;", function(match)
    local newID = string.format("&lt;ID&gt;%d&lt;/ID&gt;", idCounter)
    idCounter = idCounter + 1
    return newID
  end)

  -- Write modified content back to the original file
  local modifiedFile = io.open(filePath, "w")
  if not modifiedFile then
    print("Failed to write to the original file: " .. filePath)
    return
  end

  modifiedFile:write(newContent)
  modifiedFile:close()
  print("IDs have been successfully reassigned and saved!")
  print("Total IDs: " .. idCounter-1)
end

reassignIDs()
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end


</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>2</ID>
      <Description>"List ID-Description pairs in .CT file"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Define Lua Script to process &lt;CheatEntry&gt; with proper handling for tabs and spaces
{$lua}
--NO_ACTIVATE
if syntaxcheck then return end
if memrec then print(memrec.Description) end
getLuaEngine().menuItem5.doClick()
-- Lua Script for Cheat Engine to parse .CT file and display ID-Description pairs

function parseAndDisplayCT()
    -- User-defined base indentation to subtract
    local baseIndentation = 6

    -- Open a file dialog to select the .CT file
    local dialog = createOpenDialog()
    dialog.Filter = "Cheat Table files (*.CT)|*.CT"
    dialog.Title = "Select a Cheat Table file"

    if not dialog:execute() then
        print("No file selected.")
        return
    end

    local fileName = dialog.FileName

    -- Read file content
    local file = io.open(fileName, "r")
    if not file then
        print("Failed to open the file.")
        return
    end
    local xmlText = file:read("*all")
    file:close()

    -- Function to decode HTML entities
    local function decodeHTMLEntities(text)
        local entities = {
            ["&amp;lt;"] = "&lt;",
            ["&amp;gt;"] = "&gt;",
            ["&amp;amp;"] = "&amp;",
            ["&amp;quot;"] = "\"",
            ["&amp;apos;"] = "'"
        }
        return (text:gsub("&amp;.-;", entities))
    end

    -- Function to parse XML and calculate depth based on leading whitespace
    local function parseXMLByIndentation(xml)
        local entries = {}
        local pattern = "([ \t]*)&lt;ID&gt;(.-)&lt;/ID&gt;%s*&lt;Description&gt;(.-)&lt;/Description&gt;"

        for indent, id, description in xml:gmatch(pattern) do
            local rawDepth = #indent / 2  -- Assume 2 spaces or 1 tab equals one level
            local adjustedDepth = math.max(0, math.floor(rawDepth) - baseIndentation)  -- Adjust depth
            id = decodeHTMLEntities(id)
            description = decodeHTMLEntities(description)
            table.insert(entries, {id = id, description = description, depth = adjustedDepth})
        end

        return entries
    end

    -- Parse the XML content
    local entries = parseXMLByIndentation(xmlText)

    -- Display formatted output
    print("Parsed ID-Description pairs:")
    for _, entry in ipairs(entries) do
        local indent = string.rep("  ", entry.depth)
        print(indent .. entry.id .. ": " .. entry.description)
    end
end

parseAndDisplayCT()

[DISABLE]
{$asm}
</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
  <LuaScript>function onMemRecPostExecute(memoryrecord, newState, succeeded )
    if memoryrecord.Type == vtAutoAssembler and memoryrecord.Script:find("NO_ACTIVATE") and newState and succeeded then
        memoryrecord.disableWithoutExecute()
    end
end

</LuaScript>
</CheatTable>
