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)
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 ♥