CT Memrec Manipulation Scripts

Want Cheat Engine to do something specific and no idea how to do that, ask here. (From simple scripts to full trainers and extensions)
Post Reply
User avatar
EpicBirdi
Fearless Donors
Fearless Donors
Posts: 64
Joined: Sat Jul 21, 2018 2:22 pm
Reputation: 58

CT Memrec Manipulation Scripts

Post by EpicBirdi »

I spent the better half of my day writing up these functions, just for ease of use for myself, and wanted to share. I'm sure somebody else will find them useful.
Thanks to aSwedishMagyar and Dark Byte on CEF for some help figuring things out.

destroyMemrec(memrec)
Remove a memory record from the table, given its Description or associated numerical ID.
Spoiler

Code: Select all

function destroyMemrec(memrec)
  local al=getAddressList()
  for i=0,al.Count-1 do
    -- Check if the input is a given memory record's description or its unique ID match input, and destroy it if found. ID is useful when you have multiple identical descriptions.
    if al[i].Description == memrec or al[i].ID == memrec then
       al[i].destroy()
       break
    end
  end
end

Example Usage:
destroyMemrec(43)


setGroupSettings(memRec,gOptions)
Sets the given Group Header options to the given memory record, again by its description or ID.
Spoiler

Code: Select all

function setGroupSettings(memRec,gOptions)
  local al=getAddressList()
  for i=0,al.Count-1 do
    --Checks for memRec description and ID
    if al[i].Description == memRec or al[i].ID == memrec then
      --Input should be formatted literally: "[moHideChildren,moDeactivateChildrenAsWell]"
      al[i].Options = gOptions
    end
  end
end

Example Usage:
setGroupSettings("Group 4","[moHideChildren,moDeactivateChildrenAsWell]")


printTableData()
It's the longest function here, but probably half of it is comments.
Prints a long list of data associated with every memory record in the table. I wasn't sure of a use case for this, but maybe somebody else will. I just wanted a few things and decided to flesh it out completely, barring Scripts/Hotkeys/DDLs.
Extra checks at the end clean up what isn't necessary on a per-record basis (blank addresses, empty offsets, etc).
Spoiler

Code: Select all

function printTableData()
  --Get Address List
  local al=getAddressList()
  --Define new empty array/table
  local tableDArray = {}
  for i=0,al.Count-1 do
  --Iterate through the table
    --Storing the current entry's offset count
    local COC = al[i].OffsetCount
    --Check if there's any offsets to add
    if COC > 0 then
      --Store current entry's index
      CA = al[i]
      --Create new temporary array/table
      OT = {}
      --Create new Offset string
      OS = "{"
      --Iterate for every offset
      for h=0,COC-1 do
        --Add each offset to our temporary array/table
        OT[h] = CA.Offset[h]
      end
      for h=0,#OT do
        --Add every offset to our Offset string
        --"{Offset1, Offset2, ..."
        OS = OS..OT[h]..", "
      end
      --Remove the excess ", " from after the final offset in the string
      OS = OS:sub(1,-3)
      --Close off the string with its ending bracket
      OS = OS.."}"
    else
      --Nothing to add
      OS = "No Offsets"
    end

    --Type table
    typeSetting = {
[0] = "vtByte, Byte",
[1] = "vtWord, Word, 2 Bytes",
[2] = "vtDword, Dword, 4 Bytes",
[3] = "vtQword, Qword, 8 Bytes",
[4] = "vtSingle, Single, Float",
[5] = "vtDouble, Double, Double",
[6] = "vtString, String",
[7] = "vtUnicodeString",
[8] = "vtByteArray, Array of Byte",
[9] = "vtBinary, Binary",
[11] = "vtAutoAssembler, Script",
[12] = "vtPointer, Pointer",
[13] = "vtCustom, Custom",
[14] = "vtGrouped, Grouped"
}
    boolTable = {
[true] = "True",
[false] = "False"
}
    --Append the current entry's data to our array/table
    tableDArray[i] = {
"==========",                                                                     --Separator
"ID: "..al[i].ID,                                                                 --Entry's ID
"Index: "..al[i].Index,                                                           --Entry's Index
"Description: "..al[i].Description,                                               --Entry's Description
"Address (String): "..al[i].Address,                                              --Entry's Address
"Number of Offsets: "..COC,                                                       --Entry's Number of Offsets
"Offsets: "..OS,                                                                  --Entry's Offsets, if any
"Current Address: "..al[i].CurrentAddress,                                        --Entry's Currently Accessible Address
"Type: "..typeSetting[al[i].Type],                                                --Entry's Datatype
"Value: "..al[i].Value,                                                           --Entry's Value
"Selected: "..boolTable[al[i].Selected],                                          --Entry's Selection boolean
"Active: "..boolTable[al[i].Active],                                              --Entry's Active State
"Color (DEC): "..al[i].Color,                                                     --Entry's Colors (DEC)
"Color (HEX RGB): "..rgb_to_hex(al[i].Color),                                     --Entry's Colors (HEX) [RGB]
"Color (HEX BGR): "..bgr_to_hex(al[i].Color),                                     --Entry's Colors (HEX) [BGR]
"Shown as Hex: "..boolTable[al[i].ShowAsHex],                                     --Entry's Show as Hex boolean
"Shown as Signed: "..boolTable[al[i].ShowAsSigned],                               --Entry's Show as Signed boolean
"Increase Allowed: "..boolTable[al[i].AllowIncrease],                             --Entry's Show as Hex boolean
"Decrease Allowed: "..boolTable[al[i].AllowDecrease],                             --Entry's Show as Signed boolean
"Number of Children: "..al[i].Count,                                              --Entry's Number of Children
"Number of Hotkeys: "..al[i].HotkeyCount,                                         --Entry's Number of Hotkeys
"Group Options: ",                                                                --Entry's Group Options
"Collapsed: "..boolTable[al[i].Collapsed],                                        --Entry's Collapsed boolean
"Don't Save Boolean: "..boolTable[al[i].DontSave],                                --Entry's Don't Save boolean
"Dropdown Link: "..boolTable[al[i].DropDownLinked],                               --Entry's DropDownLinked boolean
"Dropdown Read Only: "..boolTable[al[i].DropDownReadOnly],                        --Entry's DropDownReadOnly boolean
"Dropdown Description Only: "..boolTable[al[i].DropDownDescriptionOnly],          --Entry's DropDownDescriptionOnly boolean
"Display as Dropdown List Item: "..boolTable[al[i].DisplayAsDropDownListItem],    --Entry's DropDownLinked boolean
"Length of Dropdown List: "..al[i].DropDownCount.." Lines",                       --Entry's DropDownCount total Lines
"Is a Group Header: "..boolTable[al[i].isGroupHeader]                       --Entry's Group Header boolean
}
    --Set iteration's removal counter to 0
    --Necessary so we insert/remove the correct table entries, if at all
    removed = 0
    --Check if we have an Address (Regular Group Headers and Scripts won't have one)
    if al[i].Address == "" then
      --Delete the "Address: " line if we don't need it
      table.remove(tableDArray[i],5)
      removed = removed + 1
    end
    --Check if we have any offsets
    if COC == 0 then
      --Delete the "Offsets: " line if we don't need it
      table.remove(tableDArray[i],7-removed)
      removed = removed + 1
    end
    --Check if the "Current Address" value is 0, being an invalid pointer, group, etc.
    if al[i].CurrentAddress == 0 then
      --Delete the "Current Address: " line if we don't need it
      table.remove(tableDArray[i],8-removed)
      removed = removed + 1
    end
    --Specifically for Strings, Binary, AOB, or Custom
    if al[i].Type == 6 or al[i].Type == 8 or al[i].Type == 9 or al[i].Type == 13 then
      if al[i].Type == 6 then --String
        if al[i].String.Unicode == true then
          tU = "True"
        else
          tU = "False"
        end
        table.insert(tableDArray[i],9,"     String Size: "..al[i].String.Size.."\n     Unicode: "..tU)
        removed = removed - 1
      elseif al[i].Type == 8 then --Array of Bytes
        table.insert(tableDArray[i],9,"     AOB Size: "..al[i].Aob.Size)
        removed = removed - 1
      elseif al[i].Type == 9 then --Binary
        table.insert(tableDArray[i],9,"     Starting Bit: "..al[i].Binary.Startbit.."\n     Number of Bits: "..al[i].Binary.Size)
        removed = removed - 1
      elseif al[i].Type == 13 then --Custom Type
        table.insert(tableDArray[i],9,"     Custom Type Name: "..al[i].CustomTypeName)
        removed = removed - 1
      end
    end
    --Check if we have an empty Value
    if al[i].Value == "" then
      --Delete the "Value: " line if we don't need it
      table.remove(tableDArray[i],10-removed)
      removed = removed + 1
    end
    --Check if there's Group Options or not
    if al[i].Options == "[]" then
      --Append to the "Group Options: " line
      table.insert(tableDArray[i],23-removed,"     None")
      removed = removed - 1
    else
      --Store the current Entry's Group Options
      gOptions = al[i].Options
      --Trim off the brackets "[...]"
      gOptions = string.sub(gOptions,2,-2)
      --Iterate through the string, stopping at any given comma "," and for every part until then or end of string:
      for y in string.gmatch(gOptions, "[^,]+") do
        --Append to the "Group Options: " line
        table.insert(tableDArray[i],23-removed,"     "..y)
        removed = removed - 1
      end
    end
    --Check if there's a linked DropDown memrec
    if al[i].DropDownLinked == true then
      table.insert(tableDArray[i],26-removed,"     Linked Memory Record Dropdown List From: "..al[i].DropDownLinkedMemrec)
    end
  end
  --After iterating through every table entry:
  --Iterate through the built data array/table
  for i=0,#tableDArray do
    --Store current array from the main array/table
    local c = tableDArray[i]
    --Iterate through each entry from the main data array/table
    for h=0,#c do
      --Printing each line, containing data for every table entry
      print(c[h])
    end
  end
end








Example Printout:
Display as Dropdown List Item: False 
Length of Dropdown List: 0 Lines 
 
========== 
ID: 44 
Index: 12 
Description: No description 
Address (String): 500 
Number of Offsets: 0 
Current Address: 1280 
Type: vtString, String 
     String Size: 5
     Unicode: True 
Value: ?? 
Selected: False 
Active: True 
Color (DEC): -2147483640 
Color (HEX RGB): 0x000000 
Color (HEX BGR): 0x000000 
Shown as Hex: False 
Shown as Signed: False 
Increase Allowed: False 
Decrease Allowed: False 
Number of Children: 1 
Number of Hotkeys: 0 
Group Options:  
     moHideChildren 
     moActivateChildrenAsWell 
     moDeactivateChildrenAsWell 
     moRecursiveSetValue 
     moAllowManualCollapseAndExpand 
     moManualExpandCollapse 
Collapsed: False 
Don't Save Boolean: False 
Dropdown Link: True 
     Linked Memory Record Dropdown List From: lol3 
Dropdown Read Only: True 
Dropdown Description Only: True 
Display as Dropdown List Item: True 
Length of Dropdown List: 2 Lines 
 
========== 
ID: 45 
Index: 13
...


Associated with the above:
bgr_to_hex(col) && rgb_to_hex(col)
You can set a Memrec.Color = 0x123456 in hex, but pulling it results in decimal, so these were written to get both the RGB value and the BGR value, which lua prefers. If you choose to take the above function, take these as well for the colors.
Spoiler

Code: Select all

function rgb_to_hex(col)
  if col == -2147483640 then --Default black color
    return "0x000000"   --Otherwise it returns 0xFFFFFF, which is incorrect (white)
  else
    local b, g, r = string.match(string.format("%06x", col), "([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")
    return "0x"..string.upper(r..g..b) --Returns properly formatted RGB
  end
end

function bgr_to_hex(col)
  if col == -2147483640 then --Default black color
    return "0x000000"   --Otherwise it returns 0xFFFFFF, which is incorrect (white)
  else
    local b, g, r = string.match(string.format("%06x", col), "([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")
    return "0x"..string.upper(b..g..r) --Returns properly formatted BGR
  end
end


childAppend(memrec,parent,newindex)
Allows you to move a memory record from anywhere in your table, appending it as a child to a desired parent in whichever index place you want, within new bounds. If your placement makes a total of 3 children, don't try and place it as the 4th index, y'know?
Indexes are ordered [0,1,2,...], 0 being the first child under a parent/group.
As with the other functions, description or ID work for both memrec and parent arguments.
Spoiler

Code: Select all

function childAppend(memrec, parent, newindex)
  local al=getAddressList()
  for i=0,al.Count-1 do
    if al[i].Description == parent or al[i].ID == parent then
       --find the Parent to append onto
       trueParent = al[i]
    end
  end
  for i=0,al.Count-1 do
    if al[i].Description == memrec or al[i].ID == memrec then
      --find the memory record you want to move and append it to the desired parent
      thisMem = al[i]
      thisMem.appendToEntry(trueParent)
    end
  end
  --grab the new/current parent
  local parent = thisMem.Parent
  if parent.Count < newindex+1 then
    --error/print("New Index out of Bounds") --Can only move the index within bounds
    return
  end
  if parent==nil then return end --Don't try moving the index on nothing

  list={} --new table

  for i=0,parent.Count-1 do
    if parent[i] ~= thisMem then
      --insert every undesired memrec into the table, ordered as-is
      table.insert(list,parent[i])
    end
  end
  --insert the desired memrec into the table, exactly where you want it
  table.insert(list,newindex+1, thisMem)
  --the list is now ordered according to the requested order
  for i=1,#list do
    --replace the children in the correct order
    list[i].appendToEntry(parent)
  end
end

Example Usage:
childAppend(33,"Group 4",1)
childAppend("Health",20,0)


createMemrec(memDesc, memAdd, memOffCount, memType, memColor, memOffs, memAAScript, memActive, memHex, memSigned)
The one that started my quest for proper table manipulation, and is fairly incomplete, but not hard to add on. I'm sure others have made better functions already, but this is what I ended up with for now.
The memAAScript argument can be passed literally or as a variable containing valid syntax. Examples commented in.
If the input for Offsets is too few, it will populate the remainder of OffsetCount with 0's. If OffsetCount is too low, it doesn't add extra. A case could just be added for if memOffs.Count > memOffCount, etc. Again, not super complete. I spent a lot more time on the others.
Spoiler

Code: Select all

function createMemrec(memDesc, memAdd, memOffCount, memType, memColor, memOffs, memAAScript, memActive, memHex, memSigned, memHeader)
  local al=getAddressList()
-- Create a new Memory Record
  local newMemRec = al.createMemoryRecord()
-- Assign it data:
  --Address
  newMemRec.setAddress(memAdd)

  --Description
  newMemRec.setDescription(memDesc)

  --Number of Offsets
  newMemRec.setOffsetCount(memOffCount)

  --Datatype | This can be numerical or regular type:
  newMemRec.Type = memType
      --vtByte=0
      --vtWord=1
      --vtDword=2
      --vtQword=3
      --vtSingle=4
      --vtDouble=5
      --vtString=6
      --vtUnicodeString=7 --Only used by autoguess
      --vtByteArray=8
      --vtBinary=9
      --vtAutoAssembler=11
      --vtPointer=12 --Only used by autoguess and structures
      --vtCustom=13
      --vtGrouped=14

  --Check if this is the Auto Assembler datatype. If it is, set the provided AA script as its script.
  --Valid Script syntax can be either:
--babysFirstScript = ([[
--[ENABLE]
--{$lua}
--print("Hello World")
--{$asm}
--[DISABLE]
--]])
  -- or using linebreaks ( \n ):
--babysFirstScript = ([[[ENABLE]\n{$lua}\nprint("Hello World")\n{$asm}\n[DISABLE]\n]])
  if newMemRec.Type == 11 then
    newMemRec.Script = memAAScript
  end

  --Color, use 0x000000 hex format ideally
  newMemRec.Color = memColor

  --If there's one or more offsets to add, add them
  --Valid Offset input syntax: {15,"20",0x30,-0x1A89}
  local OC = newMemRec.getOffsetCount()
  if OC > 0 then
     for i=0, OC-1 do
       local CO = memOffs[i+1] --Starts at the first entry in the offset array/table
       newMemRec.setOffset(i,CO) --Sets the current offset to its input equivalent. If there isn't enough input offsets to fill in, it defaults to 0.
     end
  end

-- Active check
  if memActive ~= true then            -- Checks if the input is literally "true", otherwise it'll be false
    newMemRec.Active = false
  else
    newMemRec.Active = true
  end

-- Show as Hex check
  if memHex ~= true then
    newMemRec.ShowAsHex = false
  else
    newMemRec.ShowAsHex = true
  end

-- Show as Signed check
  if memSigned ~= true then
    newMemRec.ShowAsSigned = false
  else
    newMemRec.ShowAsSigned = true
  end

-- Group Header check
  if memHeader ~= true then
    newMemRec.isGroupHeader = false
  else
    newMemRec.isGroupHeader = true
  end

-- End of Create Memrec Function
end


Example Usage:
createMemrec("MyRecord","Player_Base",4,vtDword,0xA3AFF6,{15,"20",0x30,-0x1A89},babysFirstScript,nil,h,true,false)
The only thing left I could think to add outright would be one to edit the DropDownList properties more easily, and I know there's working functions out there already (I use one from mgr.inz.Player).. for the future.


That aside, I do wonder if anybody's up for refining these a bit. I'm no genius but I know I can simplify some of these. I tried the most with printTableData() and it probably shows. Thanks for any feedback, if at all ♥
Last edited by EpicBirdi on Wed May 11, 2022 7:35 pm, edited 1 time in total.

User avatar
LeFiXER
LeFixer
LeFixer
Posts: 478
Joined: Wed Mar 24, 2021 9:35 am
Reputation: 242

Re: CT Memrec Manipulation Scripts

Post by LeFiXER »

Code: Select all

function rgb_to_hex(col)
  if col == -2147483640 then --Default black color
    return "0x000000"   --Otherwise it returns 0xFFFFFF, which is incorrect (white)
  else
    local b, g, r = string.match(string.format("%06x", col), "([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")
    return "0x"..string.upper(r..g..b) --Returns properly formatted RGB
  end
end
string.upper isn't required here

Code: Select all

function rgb_to_hex(col)
  if col == -2147483640 then --Default black color
    return "0x000000"   --Otherwise it returns 0xFFFFFF, which is incorrect (white)
  else
    local b, g, r = string.match(string.format("%06X", col), "([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")
    return r..g..b --Returns properly formatted RGB
  end
end
X = uppercase, x = lowercase. Same for when you're formatting a string; S,s and so forth.

Although, I thought I would provide my version of RGBToHex <> HexToRGB functions;

Code: Select all

function HexToRGB(hex)
  hex = string.format('%X', hex)
  r = tonumber(string.sub(hex,1,2),16)
  g = tonumber(string.sub(hex,3,4),16)
  b = tonumber(string.sub(hex,5,6),16)
  print(r .. ',' .. g .. ','.. b)
  return r,g,b
end

HexToRGB(0xFFFFFF)

function RGBToHex(r,g,b)
  local result = string.format('0x%02X%02X%02X', b,g,r)
  print(result)
  return result
end

RGBToHex(255,0,0)

User avatar
EpicBirdi
Fearless Donors
Fearless Donors
Posts: 64
Joined: Sat Jul 21, 2018 2:22 pm
Reputation: 58

Re: CT Memrec Manipulation Scripts

Post by EpicBirdi »

LeFiXER wrote:
Sat Aug 21, 2021 11:11 am
...
Thanks for the feedback, and for sharing!

User avatar
dharmang1910
Expert Cheater
Expert Cheater
Posts: 120
Joined: Thu Jun 08, 2017 4:16 am
Reputation: 183

Re: CT Memrec Manipulation Scripts

Post by dharmang1910 »

Thank you for sharing script. I have used your script with little modification in one of the my table here.
viewtopic.php?f=4&t=18775

Post Reply

Who is online

Users browsing this forum: No registered users