Difference between revisions of "Lua:Class:Addresslist"

From Cheat Engine
Jump to navigation Jump to search
(Verified Lua-exposed properties/methods from source. Added 13 examples, noted unexposed properties (SelCount, colors, events). Fixed descriptions, enhanced indexing notes, improved structure.)
 
Line 1: Line 1:
 
[[Category:Lua]]
 
[[Category:Lua]]
Addresslist '''class''': ('''Inheritance''': ''[[Lua:Class:Panel|Panel]]''->''[[Lua:Class:WinControl|WinControl]]''->''[[Lua:Class:Control|Control]]''->''[[Lua:Class:Component|Component]]''->''[[Lua:Class:Object|Object]]'')
+
'''AddressList''' '''class''': ('''Inheritance''': ''[[Lua:Class:Panel|Panel]]''->''[[Lua:Class:WinControl|WinControl]]''->''[[Lua:Class:Control|Control]]''->''[[Lua:Class:Component|Component]]''->''[[Lua:Class:Object|Object]]'')
  
The AddressList class represents the list of memory records (cheat entries) in Cheat Engine.
+
The AddressList class represents Cheat Engine's address list (also known as the cheat table), which is the primary container for managing [[Lua:Class:MemoryRecord|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.
It provides access to all records, selection, appearance, and event handling for the address list.
+
 
 +
The AddressList is accessible through the [[Lua:getAddressList|getAddressList]] function, which returns the main address list instance from Cheat Engine's main form.
  
 
== Properties ==
 
== Properties ==
{| class="wikitable" style="width:100%"
+
 
 +
{|class="wikitable" style="width:100%"
 
! Property
 
! Property
 
! Type
 
! Type
 +
! Access
 
! Description
 
! Description
|-
 
| LoadedTableVersion
 
| Integer
 
| Returns the tableVersion of the last loaded table.
 
 
|-
 
|-
 
| Count
 
| Count
 
| Integer
 
| Integer
| The number of records in the table.
+
| Read-only
|-
+
| The total number of [[Lua:Class:MemoryRecord|MemoryRecord]] entries in the address list (all levels, including children).
| SelCount
 
| Integer
 
| The number of records that are selected.
 
 
|-
 
|-
 
| SelectedRecord
 
| SelectedRecord
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| The main selected record.
+
| 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[]
+
| MemoryRecord[index]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Array to access the individual memory records.
+
| 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]
 
| [index]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Default accessor for memory records.
+
| Read-only
|-
+
| Default array accessor. Equivalent to '''MemoryRecord[index]'''.
| CheckboxActiveSelectedColor
 
| Color
 
| Color for active and selected checkboxes.
 
|-
 
| CheckboxActiveColor
 
| Color
 
| Color for active checkboxes.
 
|-
 
| CheckboxSelectedColor
 
| Color
 
| Color for selected checkboxes.
 
|-
 
| CheckboxColor
 
| Color
 
| Color for checkboxes.
 
|-
 
| SelectedBackgroundColor
 
| Color
 
| Color for the selected row background.
 
|-
 
| SelectedSecondaryBackgroundColor
 
| Color
 
| Secondary color for selected row background.
 
|-
 
| ExpandSignColor
 
| Color
 
| Color for the expand/collapse sign.
 
|-
 
| IncreaseArrowColor
 
| Color
 
| Color for the increase arrow.
 
|-
 
| DecreaseArrowColor
 
| Color
 
| Color for the decrease arrow.
 
 
|}
 
|}
 +
 +
=== Properties Not Exposed to Lua ===
 +
 +
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 ==
 
== Methods ==
{| class="wikitable" style="width:100%"
+
 
 +
{|class="wikitable" style="width:100%"
 
! Method
 
! Method
 
! Parameters
 
! Parameters
Line 82: Line 59:
 
| None
 
| None
 
| Integer
 
| Integer
| Returns the number of memory records.
+
| Returns the total number of memory records in the address list.
 
|-
 
|-
 
| getMemoryRecord
 
| getMemoryRecord
| Integer (index)
+
| Integer (index) OR String (description)
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Returns the memory record at the given index.
+
| 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
 
| getMemoryRecordByDescription
 
| String (description)
 
| String (description)
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Returns the memory record with the given description.
+
| Returns the first memory record with the specified description. Returns '''nil''' if not found. Uses an internal hash table for fast lookups.
 
|-
 
|-
 
| getMemoryRecordByID
 
| getMemoryRecordByID
| Integer (ID)
+
| Integer (id)
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Returns the memory record with the given ID.
+
| Returns the memory record with the specified unique ID. Returns '''nil''' if not found.
 
|-
 
|-
 
| createMemoryRecord
 
| createMemoryRecord
 
| None
 
| None
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
| Creates a generic cheat table entry and adds it to the list.
+
| 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 [[Lua:Class:MemoryRecord|MemoryRecord]] object.
 
|-
 
|-
 
| getSelectedRecords
 
| getSelectedRecords
 
| None
 
| None
| Table of [[Lua:Class:MemoryRecord|MemoryRecord]]
+
| Table
| Returns a table containing all the selected records.
+
| Returns a table (1-indexed) containing all currently selected [[Lua:Class:MemoryRecord|MemoryRecord]] objects. Returns '''nil''' if no records are selected.
 +
|-
 +
| getSelectedRecord
 +
| None
 +
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 +
| Returns the currently selected memory record. Same as accessing the '''SelectedRecord''' property. Returns '''nil''' if no record is selected.
 +
|-
 +
| setSelectedRecord
 +
| [[Lua:Class:MemoryRecord|MemoryRecord]] (memrec)
 +
| None
 +
| Sets the currently selected memory record, deselecting all others. Same as setting the '''SelectedRecord''' property.
 
|-
 
|-
 
| doDescriptionChange
 
| doDescriptionChange
 
| None
 
| None
 
| None
 
| None
| Shows the GUI window to change the description of the selected entry.
+
| 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
 
| doAddressChange
 
| None
 
| None
 
| None
 
| None
| Shows the GUI window to change the address of the selected entry.
+
| 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
 
| doTypeChange
 
| None
 
| None
 
| None
 
| None
| Shows the GUI window to change the type of the selected entries.
+
| 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
 
| doValueChange
 
| None
 
| None
 
| None
 
| None
| Shows the GUI window to change the value of the selected entries.
+
| 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.
|-
 
| getSelectedRecord
 
| None
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| Gets the main selected memory record.
 
|-
 
| setSelectedRecord
 
| [[Lua:Class:MemoryRecord|MemoryRecord]]
 
| None
 
| Sets the currently selected memory record (unselects all others).
 
 
|-
 
|-
 
| disableAllWithoutExecute
 
| disableAllWithoutExecute
 
| None
 
| None
 
| None
 
| None
| Disables all memory records without executing their [Disable] section.
+
| 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
 
| rebuildDescriptionCache
 
| None
 
| None
 
| None
 
| None
| Rebuilds the description-to-record lookup table.
+
| 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.
 
|}
 
|}
  
== Events / Callbacks ==
+
=== Inherited Properties and Methods ===
{| class="wikitable" style="width:100%"
+
 
! Event
+
As AddressList inherits from Panel, it also has access to all [[Lua:Class:Panel|Panel]], [[Lua:Class:WinControl|WinControl]], [[Lua:Class:Control|Control]], [[Lua:Class:Component|Component]], and [[Lua:Class:Object|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.
! Parameters
+
 
! Description
+
Useful inherited properties include:
|-
+
* '''Visible''' (boolean) - Show/hide the address list panel
| OnDescriptionChange
+
* '''Enabled''' (boolean) - Enable/disable user interaction
| function(addresslist, memrec):boolean
+
* '''PopupMenu''' ([[Lua:Class:PopupMenu|PopupMenu]]) - Custom context menu for the address list
| Called when the user initiates a description column change on a record. Return true if you handle it, false for normal behaviour.
+
 
|-
+
== Usage Examples ==
| OnAddressChange
+
 
| function(addresslist, memrec):boolean
+
=== Basic Address List Access ===
| Called when the user initiates an address column change on a record. Return true if you handle it, false for normal behaviour.
+
 
|-
+
<pre>
| OnTypeChange
+
-- Get the main address list
| function(addresslist, memrec):boolean
+
local addressList = getAddressList()
| Called when the user initiates a type column change on a record. Return true if you handle it, false for normal behaviour.
+
 
|-
+
-- Get the count of all records
| OnValueChange
+
print("Total records: " .. addressList.Count)
| function(addresslist, memrec):boolean
+
 
| Called when the user initiates a value column change on a record. Return true if you handle it, false for normal behaviour.
+
-- Get selected records to find selection count
|-
+
local selected = addressList.getSelectedRecords()
| OnAutoAssemblerEdit
+
if selected then
| function(addresslist, memrec)
+
  print("Selected records: " .. #selected)
| Called when the user initiates a memory record AA script edit. This function will be responsible for changing the memory record.
+
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
 +
</pre>
 +
 
 +
=== Creating Memory Records ===
 +
 
 +
<pre>
 +
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)
 +
</pre>
 +
 
 +
=== Finding Records by Description ===
 +
 
 +
<pre>
 +
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"
 +
</pre>
  
== Other Functions ==
+
=== Finding Records by ID ===
* '''MouseHighlightedRecord()''' — Returns the memory record that the mouse points at, or nil if nothing.
 
  
== Examples ==
 
 
<pre>
 
<pre>
-- Print all memory record descriptions
+
local addressList = getAddressList()
for i = 0, AddressList.Count - 1 do
+
 
   print(AddressList[i].Description)
+
-- 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
 
end
  
-- Create a new memory record
+
-- IDs are unique and persistent within a session
local newrec = AddressList:createMemoryRecord()
+
-- Useful for tracking records across description changes
newrec.Description = "My New Entry"
+
</pre>
newrec.Address = "00400000"
+
 
 +
=== Working with Selected Records ===
 +
 
 +
<pre>
 +
local addressList = getAddressList()
  
 
-- Get all selected records
 
-- Get all selected records
local selected = AddressList:getSelectedRecords()
+
local selected = addressList.getSelectedRecords()
for i, rec in ipairs(selected) do
+
if selected then
   print("Selected:", rec.Description)
+
  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
 +
</pre>
 +
 
 +
=== Triggering UI Dialogs ===
 +
 
 +
<pre>
 +
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
 +
</pre>
 +
 
 +
=== Managing Auto Assembler Scripts ===
 +
 
 +
<pre>
 +
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()
 +
</pre>
 +
 
 +
=== Iterating Through All Records ===
 +
 
 +
<pre>
 +
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
 
end
 +
print("Total active: " .. activeCount)
  
-- Change the selected record
+
-- Find all records of a specific type
AddressList:setSelectedRecord(AddressList[0])
+
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
 
</pre>
 
</pre>
 +
 +
=== Batch Operations ===
 +
 +
<pre>
 +
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
 +
</pre>
 +
 +
=== Rebuilding Description Cache ===
 +
 +
<pre>
 +
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
 +
</pre>
 +
 +
=== Working with Hierarchical Records ===
 +
 +
<pre>
 +
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)
 +
</pre>
 +
 +
=== Advanced: Monitoring Changes ===
 +
 +
<pre>
 +
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
 +
</pre>
 +
 +
== Important Notes ==
 +
 +
=== Record Indexing ===
 +
 +
* 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 ===
 +
 +
* '''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 ===
 +
 +
* 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 ===
 +
 +
* 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 ===
 +
 +
* Address list operations should be performed on the main thread
 +
* Use [[Lua:synchronize|synchronize]] if accessing from background threads
 +
* UI dialog methods ('''do*Change''') must be called from the main thread and will block script execution
  
 
{{LuaSeeAlso}}
 
{{LuaSeeAlso}}
  
 
=== Related Functions ===
 
=== Related Functions ===
* [[Lua:getMainForm|getMainForm]]
+
* [[Lua:getAddressList|getAddressList]] - Get the main AddressList object
* [[Lua:getAddressList|getAddressList]]
+
* [[Lua:getMainForm|getMainForm]] - Get the main Cheat Engine form
  
 
=== Related Classes ===
 
=== Related Classes ===
* [[Lua:Class:MemoryRecord|MemoryRecord]]
+
* [[Lua:Class:MemoryRecord|MemoryRecord]] - Individual address list entries
 +
* [[Lua:Class:MemoryRecordHotkey|MemoryRecordHotkey]] - Hotkeys attached to memory records
 +
* [[Lua:Class:Panel|Panel]] - Parent class
 +
* [[Lua:Class:WinControl|WinControl]] - Grandparent class
 +
* [[Lua:Class:Control|Control]] - Base control class
 +
* [[Lua:Class:Component|Component]] - Base component class

Latest revision as of 20:20, 25 October 2025

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]