Lua:Class:Addresslist

From Cheat Engine
(Redirected from Addresslist)
Jump to navigation Jump to search

AddressList class: (Inheritance: Panel->WinControl->Control->Component->Object)

The AddressList class represents Cheat Engine's address list (also known as the cheat table), which is the primary container for managing MemoryRecord entries. This class provides methods to create, retrieve, and manipulate memory records, as well as trigger UI updates for description, address, type, and value changes.

The AddressList is accessible through the getAddressList function, which returns the main address list instance from Cheat Engine's main form.

Properties[edit]

Property Type Access Description
Count Integer Read-only The total number of MemoryRecord entries in the address list (all levels, including children).
SelectedRecord MemoryRecord Read/Write Gets or sets the currently selected memory record. Returns nil if no record is selected. Setting this property deselects all other records and selects the specified one.
MemoryRecord[index] MemoryRecord Read-only Array accessor to retrieve memory records by index (0-based). Can also be accessed using function call syntax: AddressList[index]. Same as getMemoryRecord(index). Alternatively, can be accessed with a string to search by description.
[index] MemoryRecord Read-only Default array accessor. Equivalent to MemoryRecord[index].

Properties Not Exposed to Lua[edit]

The following properties are available in the Pascal TAddressList class but are not exposed to Lua scripts:

  • LoadedTableVersion
  • SelCount
  • CheckboxActiveSelectedColor, CheckboxActiveColor, CheckboxSelectedColor, CheckboxColor
  • SelectedBackgroundColor, SelectedSecondaryBackgroundColor
  • ExpandSignColor, IncreaseArrowColor, DecreaseArrowColor
  • MouseHighlightedRecord
  • OnDescriptionChange, OnAddressChange, OnTypeChange, OnValueChange, OnAutoAssemblerEdit (event callbacks)

These properties are used internally by Cheat Engine's UI but cannot be accessed or modified from Lua scripts.

Methods[edit]

Method Parameters Returns Description
getCount None Integer Returns the total number of memory records in the address list.
getMemoryRecord Integer (index) OR String (description) MemoryRecord Returns the memory record at the specified index (0-based). Also accepts a string description to search by description. Returns nil if index is out of bounds or description not found.
getMemoryRecordByDescription String (description) MemoryRecord Returns the first memory record with the specified description. Returns nil if not found. Uses an internal hash table for fast lookups.
getMemoryRecordByID Integer (id) MemoryRecord Returns the memory record with the specified unique ID. Returns nil if not found.
createMemoryRecord None MemoryRecord Creates a new memory record and adds it to the address list. The record is initialized with default values (description: "Plugin Address", address: "0", type: vtDword). Returns the newly created MemoryRecord object.
getSelectedRecords None Table Returns a table (1-indexed) containing all currently selected MemoryRecord objects. Returns nil if no records are selected.
getSelectedRecord None MemoryRecord Returns the currently selected memory record. Same as accessing the SelectedRecord property. Returns nil if no record is selected.
setSelectedRecord MemoryRecord (memrec) None Sets the currently selected memory record, deselecting all others. Same as setting the SelectedRecord property.
doDescriptionChange None None Shows the GUI window to change the description of the selected entry. Opens a dialog allowing the user to modify the description. Equivalent to double-clicking the description column.
doAddressChange None None Shows the GUI window to change the address of the selected entry. Opens a dialog allowing the user to modify the address and pointer settings. Equivalent to double-clicking the address column.
doTypeChange None None Shows the GUI window to change the type of the selected entries. Opens a dialog allowing the user to change the variable type. Equivalent to double-clicking the type column.
doValueChange None None Shows the GUI window to change the value of the selected entries. Opens a dialog allowing the user to modify the value. Equivalent to double-clicking the value column.
disableAllWithoutExecute None None Disables all active auto assembler script entries without executing their [DISABLE] sections. Useful for quickly disabling all scripts when detaching from a process or when scripts have failed.
rebuildDescriptionCache None None Rebuilds the internal hash table used for fast description-based lookups. Call this after making many changes to descriptions if you need to ensure getMemoryRecordByDescription reflects the latest state.

Inherited Properties and Methods[edit]

As AddressList inherits from Panel, it also has access to all Panel, WinControl, Control, Component, and Object properties and methods. However, most inherited UI properties are not typically used in scripting contexts since the AddressList is part of the main Cheat Engine form.

Useful inherited properties include:

  • Visible (boolean) - Show/hide the address list panel
  • Enabled (boolean) - Enable/disable user interaction
  • PopupMenu (PopupMenu) - Custom context menu for the address list

Usage Examples[edit]

Basic Address List Access[edit]

-- Get the main address list
local addressList = getAddressList()

-- Get the count of all records
print("Total records: " .. addressList.Count)

-- Get selected records to find selection count
local selected = addressList.getSelectedRecords()
if selected then
  print("Selected records: " .. #selected)
else
  print("Selected records: 0")
end

-- Access records by index (0-based)
if addressList.Count > 0 then
  local firstRecord = addressList[0]
  print("First record: " .. firstRecord.Description)
  
  -- Alternative syntax
  local secondRecord = addressList.getMemoryRecord(1)
  if secondRecord then
    print("Second record: " .. secondRecord.Description)
  end
end

-- Access by description (alternative to index)
local healthRec = addressList["Player Health"]
if healthRec then
  print("Found by description: " .. healthRec.Description)
end

-- Get/set selected record
local selected = addressList.SelectedRecord
if selected then
  print("Currently selected: " .. selected.Description)
  print("Value: " .. selected.Value)
end

Creating Memory Records[edit]

local addressList = getAddressList()

-- Create a basic memory record
local mr = addressList.createMemoryRecord()
mr.Description = "Player Health"
mr.Address = "game.exe+1234"
mr.Type = vtDword

-- Create multiple records
local stats = {"Health", "Mana", "Stamina"}
local offsets = {0x10, 0x14, 0x18}

for i = 1, #stats do
  local record = addressList.createMemoryRecord()
  record.Description = "Player " .. stats[i]
  record.Address = string.format("player_base+%X", offsets[i])
  record.Type = vtFloat
  record.ShowAsHex = false
end

print("Created " .. #stats .. " new records")
print("Total records now: " .. addressList.Count)

Finding Records by Description[edit]

local addressList = getAddressList()

-- Find by exact description
local healthRecord = addressList.getMemoryRecordByDescription("Player Health")
if healthRecord then
  print("Health value: " .. healthRecord.Value)
  healthRecord.Active = true
else
  print("Player Health not found")
end

-- Alternative: Search by index with description
local record = addressList.getMemoryRecord("Player Mana")
if record then
  print("Mana address: " .. record.Address)
end

-- Note: Description lookup is case-sensitive
local notFound = addressList.getMemoryRecordByDescription("player health")  -- Won't find "Player Health"

Finding Records by ID[edit]

local addressList = getAddressList()

-- Get a record's ID and store it
local healthRecord = addressList.getMemoryRecordByDescription("Player Health")
if healthRecord then
  local storedID = healthRecord.ID
  print("Stored ID: " .. storedID)
  
  -- Later, retrieve by ID (even if description changed)
  local retrievedRecord = addressList.getMemoryRecordByID(storedID)
  if retrievedRecord then
    print("Retrieved: " .. retrievedRecord.Description)
    print("Same record: " .. tostring(healthRecord == retrievedRecord))
  end
end

-- IDs are unique and persistent within a session
-- Useful for tracking records across description changes

Working with Selected Records[edit]

local addressList = getAddressList()

-- Get all selected records
local selected = addressList.getSelectedRecords()
if selected then
  print("Processing " .. #selected .. " selected records")
  
  for i = 1, #selected do
    local record = selected[i]
    print(i .. ": " .. record.Description)
    
    -- Modify all selected records
    record.Active = true
    record.Color = 0x0000FF  -- Red (BGR format)
  end
else
  print("No records selected")
end

-- Select a specific record programmatically
local targetRecord = addressList.getMemoryRecordByDescription("God Mode")
if targetRecord then
  addressList.SelectedRecord = targetRecord
  print("Selected: " .. targetRecord.Description)
end

-- Check current selection
local currentSelection = addressList.getSelectedRecord()
if currentSelection then
  print("Current selection: " .. currentSelection.Description)
end

Triggering UI Dialogs[edit]

local addressList = getAddressList()

-- Select a record first
local record = addressList.getMemoryRecordByDescription("Player Health")
if record then
  addressList.SelectedRecord = record
  
  -- Open description editor dialog
  -- addressList.doDescriptionChange()
  
  -- Open address editor dialog
  -- addressList.doAddressChange()
  
  -- Open type selector dialog
  -- addressList.doTypeChange()
  
  -- Open value editor dialog
  -- addressList.doValueChange()
  
  -- Note: These dialogs are modal and will pause script execution
  -- Uncomment the lines above to test interactively
end

Managing Auto Assembler Scripts[edit]

local addressList = getAddressList()

-- Create an auto assembler script
local script = addressList.createMemoryRecord()
script.Description = "Infinite Health"
script.Type = vtAutoAssembler
script.Script = [[
[ENABLE]
aobscan(health_code,89 0D * * * * 8B 45 08)
alloc(newmem,32)

label(code)
label(return)

newmem:
code:
  mov [health_address],#1000  // Set to 1000
  mov [edx],ecx
  jmp return

health_code:
  jmp newmem
  nop
return:
registersymbol(health_code)

[DISABLE]
health_code:
  db 89 0D * * * * 8B 45 08
unregistersymbol(health_code)
dealloc(newmem)
]]

-- Activate the script
script.Active = true

-- Later, disable all scripts without executing [DISABLE] sections
-- Useful when the process is about to close or has crashed
addressList.disableAllWithoutExecute()

Iterating Through All Records[edit]

local addressList = getAddressList()

-- Iterate through all records (including children)
print("=== All Records ===")
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  local indent = string.rep("  ", record.Parent and 1 or 0)
  
  print(string.format("%s[%d] %s = %s (%s)", 
    indent, i, record.Description, record.Value, 
    record.Active and "Active" or "Inactive"))
end

-- Find all active records
print("\n=== Active Records ===")
local activeCount = 0
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  if record.Active then
    print(record.Description)
    activeCount = activeCount + 1
  end
end
print("Total active: " .. activeCount)

-- Find all records of a specific type
print("\n=== Float Records ===")
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  if record.Type == vtFloat or record.Type == vtDouble then
    print(record.Description .. " @ " .. record.Address)
  end
end

Batch Operations[edit]

local addressList = getAddressList()

-- Deactivate all records
print("Deactivating all records...")
for i = 0, addressList.Count - 1 do
  addressList[i].Active = false
end

-- Activate records matching a pattern
print("Activating player-related records...")
local activatedCount = 0
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  if record.Description:lower():find("player") then
    record.Active = true
    activatedCount = activatedCount + 1
  end
end
print("Activated " .. activatedCount .. " records")

-- Change all values matching a condition
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  local numValue = tonumber(record.Value)
  
  if numValue and numValue < 100 then
    record.Value = "999"
    print("Changed " .. record.Description .. " to 999")
  end
end

Rebuilding Description Cache[edit]

local addressList = getAddressList()

-- Make many description changes
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  record.Description = "Modified_" .. record.Description
end

-- Rebuild the description cache for fast lookups
addressList.rebuildDescriptionCache()

-- Now lookups will work correctly
local modifiedRecord = addressList.getMemoryRecordByDescription("Modified_Player Health")
if modifiedRecord then
  print("Found: " .. modifiedRecord.Description)
end

-- Note: The cache is automatically updated for individual changes,
-- but rebuilding is useful after bulk modifications or when debugging

Working with Hierarchical Records[edit]

local addressList = getAddressList()

-- Create a parent group
local group = addressList.createMemoryRecord()
group.Description = "Player Stats"
group.IsGroupHeader = true
group.Options = "[moActivateChildrenAsWell,moDeactivateChildrenAsWell]"

-- Create children and attach to group
local childDescriptions = {"Health", "Mana", "Stamina"}
for i, desc in ipairs(childDescriptions) do
  local child = addressList.createMemoryRecord()
  child.Description = desc
  child.Type = vtDword
  child.Address = string.format("player_base+%X", (i-1) * 4)
  child.appendToEntry(group)
end

-- Activate the group (children will activate too)
group.Active = true

-- Note: All records are still in the flat addressList.Count
-- Parent-child relationships are maintained separately
print("Total records: " .. addressList.Count)
print("Group children: " .. group.Count)

Advanced: Monitoring Changes[edit]

local addressList = getAddressList()

-- Store initial state
local recordStates = {}
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  recordStates[record.ID] = {
    description = record.Description,
    value = record.Value,
    active = record.Active
  }
end

-- Later, check for changes
print("=== Changes Detected ===")
for i = 0, addressList.Count - 1 do
  local record = addressList[i]
  local oldState = recordStates[record.ID]
  
  if oldState then
    if oldState.value ~= record.Value then
      print(record.Description .. " value changed: " .. 
            oldState.value .. " -> " .. record.Value)
    end
    
    if oldState.active ~= record.Active then
      print(record.Description .. " activation changed: " .. 
            tostring(oldState.active) .. " -> " .. tostring(record.Active))
    end
  end
end

Important Notes[edit]

Record Indexing[edit]

  • The MemoryRecord[index] property uses 0-based indexing
  • The getSelectedRecords() method returns a 1-indexed table (Lua convention)
  • Child indices within parent records use 0-based indexing
  • You can use AddressList[index] as a shorthand for AddressList.MemoryRecord[index]
  • You can also use AddressList["description"] to search by description

Description Lookup Performance[edit]

  • getMemoryRecordByDescription uses an internal hash table for O(1) lookups
  • The cache is automatically maintained for most operations
  • Some reserved descriptions (e.g., "BYTE", "WORD", "DWORD", "QWORD", "INT", "FLOAT", "DOUBLE") cannot be found by description as they're in the forbidden list
  • If lookups fail after many changes, call rebuildDescriptionCache()
  • Description lookups are case-sensitive

Selection Behavior[edit]

  • Setting SelectedRecord deselects all other records
  • Multiple selection is typically done through the UI (Ctrl+Click, Shift+Click)
  • getSelectedRecords() includes records at all hierarchy levels if selected
  • Selected records remain selected until explicitly changed
  • Use getSelectedRecord() or SelectedRecord property to get the main selected record

Memory Record Lifecycle[edit]

  • Creating records with createMemoryRecord() adds them to the address list
  • Records are removed from the count when deleted via memoryrecord.delete()
  • The Count property reflects all records at all hierarchy levels (including children)
  • Deleting a parent record automatically deletes all its children

Thread Safety[edit]

  • Address list operations should be performed on the main thread
  • Use synchronize if accessing from background threads
  • UI dialog methods (do*Change) must be called from the main thread and will block script execution

See also[edit]

Related Functions[edit]

Related Classes[edit]