Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Dropdown Menu Lists

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Sun Feb 08, 2015 5:45 pm    Post subject: Dropdown Menu Lists Reply with quote

Just throwing out this suggestion.

Instead of adding the dropdown options specifically for a single address, I would store the list and give it a name. Then, assign that name to the address.

I only mention this because I was recently hacking a game that had multiple addresses, but each one had the same possibility of values. So I had to add the same list of 100+ values to the 12 separate addresses, increasing the file size dramatically.
Back to top
View user's profile Send private message
MindCaged
Newbie cheater
Reputation: 0

Joined: 25 Apr 2013
Posts: 10

PostPosted: Tue Apr 28, 2015 7:28 pm    Post subject: Reply with quote

I agree. I just posted a different post about this. First of all it's really time consuming, so it'd also be good if you could modify the dropdown settings of multiple entries at once, currently it only lets you do so on individual ones. I became so desperate that I resorted to opening the file in textpad and copy/pasting the xml tags for the dropdown info to each of 256 inventory slot entries. Which also BTW really inflated the filesize by a lot.
Back to top
View user's profile Send private message
predprey
Master Cheater
Reputation: 24

Joined: 08 Oct 2015
Posts: 486

PostPosted: Tue Jan 19, 2016 1:17 pm    Post subject: Reply with quote

Would writing in this feature require a major recoding? I'm interested in coding in this function if it's not contradictory to the existing code.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 941

PostPosted: Tue Jan 19, 2016 3:46 pm    Post subject: Reply with quote

Probably by Lua, but the code itself may consider an overhead in size.
This not sure bug free.
Code:
function MRIter(process,filter,mr,parent,lv)

local function strSplit(s,pat)
  local find,sub,ps,ds = string.find,string.sub,{},{}
  local n,a,b = 1,find(s,pat,1)
  while a~=nil do
    ps[1+#ps]=sub(s,n,a-1)
    ds[1+#ds]=sub(s,a,b)
    n = b+1
    a,b = find(s,pat,n)
  end
  ps[1+#ps]=sub(s,n,-1)
  return ps,ds
end
  lv = lv or 0
  if mr==nil then mr = getAddressList()
  elseif type(mr)=='string' then
    mr = assert(getAddressList().GetMemoryRecordByDescription(mr),"Can't find mr with desc:"..mr)
  end
  local stop = mr.ID and process(mr,parent,lv) or nil -- not process root (getAddressList)
  if stop==nil then
    if type(filter)=='string' then
      local kv,pair = {},strSplit(filter,';')
      if #pair>0 then
        for i=1,#pair do
          local p = strSplit(pair[i],'=')
          if #p==2 then kv[p[1]:match("^%s*(.-)%s*$")] = p[2]:match("^%s*(.-)%s*$") end
        end
      end
      filter = function(mR)
        for k,v in pairs(kv) do
          if not tostring(mR[k]):match(v) then return false end
        end
        return true
      end
    elseif type(filter)~='function' then
      filter = false
    end
    for i=0,mr.Count-1 do
      if filter==false or filter(mr[i]) then
        stop = MRIter(process,filter,mr[i],mr,lv+1)
        if stop~=nil then break end
      end
    end
  end
  return stop
end



-- TEST --

MRIter(function(mr,p,lv)
  print(string.rep(" ",lv*2)..mr.Description)
  mr.DropDownList.Text = "1:AAA\n2:BBB\n3:CCC" -- long text to be applied to multiple records
end,
"Type="..tostring(vtString)..';Address=_res') -- 2 properties to test
-- filter is a string of form "pro1=match1;pro2=match2"
-- where the mr's pro1's value will convert to string and do
-- a string match with match1. Process the mr if all prop1,..propn match.
-- Leave it for process all mr.


updated:
typo: ... .GetMemoryRecordByDescription(mrdesc) -> .GetMemoryRecordByDescription(mr)

_________________
- Retarded.


Last edited by panraven on Wed Jan 20, 2016 6:19 am; edited 1 time in total
Back to top
View user's profile Send private message
predprey
Master Cheater
Reputation: 24

Joined: 08 Oct 2015
Posts: 486

PostPosted: Wed Jan 20, 2016 2:56 am    Post subject: Reply with quote

how did you come across the DropDownList attribute? neither the wiki page for MemoryRecord class nor CE's help file had any info on it. did you perhaps comb through CE's code to find it? are there a lot more of these hidden functions in CE? Surprised
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 941

PostPosted: Wed Jan 20, 2016 6:09 am    Post subject: Reply with quote

predprey wrote:
how did you come across the DropDownList attribute? neither the wiki page for MemoryRecord class nor CE's help file had any info on it. did you perhaps comb through CE's code to find it? are there a lot more of these hidden functions in CE? Surprised


It is from getPropertyList Lua function on a ce class object.

Alternatively, get the metatable of the ce class object, by lua function getmetatable, may get more hidden properties, but they are not nicely sorted and their use may be not documented.

@main.lua in you ce dir, or https://raw.githubusercontent.com/cheat-engine/cheat-engine/master/Cheat%20Engine/bin/main.lua
Code:
...
undefined property functions. Not all properties of all classes have been explicitly exposed to lua, but if you know the name of a property of a specific class you can still access them (assuming they are declared as published in the pascal class declaration)
getPropertyList(class) : Returns a stringlist object containing all the published properties of the specified class (free the list when done) (Note, not all classed with properties have 'published' properties. E.g: stringlist)
...


bye~

_________________
- Retarded.
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 218

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Wed Jan 20, 2016 6:56 am    Post subject: Reply with quote

Add memory records with only one DropDownList entry (not in "value:desc" format):
"myDropDownList"

then you can execute this:
Code:
myDropDownList = [[1:one
2:two
3:three]]



al=getAddressList()
for i=0,al.Count-1 do
 if al[i].DropDownList[0]=='myDropDownList' then
  al[i].DropDownList.Text = myDropDownList
 end
end

_________________
Back to top
View user's profile Send private message MSN Messenger
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 941

PostPosted: Wed Jan 20, 2016 7:17 am    Post subject: Reply with quote

mgr.inz.Player wrote:
Add memory records with only one DropDownList entry (not in "value:desc" format):
"myDropDownList"

then you can execute this:
Code:
myDropDownList = [[1:one
2:two
3:three]]



al=getAddressList()
for i=0,al.Count-1 do
 if al[i].DropDownList[0]=='myDropDownList' then
  al[i].DropDownList.Text = myDropDownList
 end
end


The marker "myDropDownList" may got overwritten into the saved *.ct with accidental saving by user, probably some other alternative checking?

ADDED:
oops, nvm, it is not a problem as the option text is static.

_________________
- Retarded.
Back to top
View user's profile Send private message
TurtleCray
How do I cheat?
Reputation: 0

Joined: 13 Dec 2009
Posts: 6

PostPosted: Thu Mar 31, 2016 9:34 am    Post subject: Reply with quote

mgr.inz.Player wrote:
Add memory records with only one DropDownList entry (not in "value:desc" format):
"myDropDownList"

then you can execute this:
Code:
myDropDownList = [[1:one
2:two
3:three]]



al=getAddressList()
for i=0,al.Count-1 do
 if al[i].DropDownList[0]=='myDropDownList' then
  al[i].DropDownList.Text = myDropDownList
 end
end


Hi,

I was trying to use your code to make a table for Factorio but it returns me this error:
Error:List index (0) out of bounds

My list follows this structure:
Code:
HotBarAddress -> XXXXXXXXXX
    Slot1 Qtd: -> +0
        Type -> +8
    Slot2 Qtd: -> +10
        Type -> +8
    Slot3 Qtd: -> +20
        Type -> +8

I would want to make the types as a dropdown list. Do you have any advice?

Thanks
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 218

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Thu Mar 31, 2016 3:22 pm    Post subject: Reply with quote

Updated script:

function addDropDownList(list, listName, DropDownReadOnly, DropDownDescriptionOnly, DisplayAsDropDownListItem)
  list - string with a list
  listName - to find this string in existing memoryrecords and replace with list
  DropDownReadOnly - optional Boolean, disallow manual user input, default is false
  DropDownDescriptionOnly - optional Boolean, only show the description part, default is false
  DisplayAsDropDownListItem - optional Boolean, make the record display values like the dropdown list, default is false





Code:
function addDropDownList(list, listName, ...)
  local DropDownReadOnly,DropDownDescriptionOnly,DisplayAsDropDownListItem=...

  local al=getAddressList()
  for i=0,al.Count-1 do
    if al[i].DropDownList.Text:match(listName) then
       al[i].DropDownList.Text = list
       al[i].DropDownReadOnly=DropDownReadOnly
       al[i].DropDownDescriptionOnly=DropDownDescriptionOnly
       al[i].DisplayAsDropDownListItem=DisplayAsDropDownListItem
    end
  end
end


myDropDownList = [[
1:one
2:two
3:three]]

myDropDownListName = 'myDropDownList'

addDropDownList(myDropDownList,myDropDownListName,true,false,true)

_________________
Back to top
View user's profile Send private message MSN Messenger
akumakuja28
Master Cheater
Reputation: 16

Joined: 28 Jun 2015
Posts: 432

PostPosted: Sun Apr 10, 2016 1:39 am    Post subject: Reply with quote

From my misunderstanding on this post Cheat table to big to upload
about how big a data structure could be(*dont use them) and suggesting he use a "Add Drop Menu" LUA script to add the drop list after Download.

I wrote this up to Add Drop List to Defined Cheat Entries.

It has some redundancy but easier to understand that way. Figure it would be best to post it here vs the thread in question.




Code:


local Drop_List_Items=[[
0:None
1:One
2:Two
255:MAX

]]---End of Drop List


local Cheat_Entries_For_Drop_Attach = {'Slot 2',"Slot 1","Slot 3"}

local TableCount = getAddressList().Count

for j=0,TableCount-1 do
     local CR = getAddressList().getMemoryRecord(j)
     local Yada = (CR.Description)

       for LC=1,#Cheat_Entries_For_Drop_Attach do
       local DropAdd = (Cheat_Entries_For_Drop_Attach[LC])


          if DropAdd==Yada then
          print('Match Found'..'  @  '..Yada)
          CR.DropDownList.Text = Drop_List_Items
          ---------------------

          -------- Options ----
          CR.DropDownReadOnly=false  ---Disallow manual user input
          CR.DropDownDescriptionOnly=true  ----Only show the description part
          CR.DisplayAsDropDownListItem=true  ---Make the record display values like the dropdownlist
          ---------------------
          end

       end
end

_________________
Back to top
View user's profile Send private message
Rhagic
Advanced Cheater
Reputation: 4

Joined: 23 Aug 2011
Posts: 94

PostPosted: Sat May 14, 2016 10:43 am    Post subject: Reply with quote

akumakuja28 wrote:
I wrote this up to Add Drop List to Defined Cheat Entries.


Thank you for posting this, it was really helpful and inspiration to write some LUA for creating memory records for repetitive entries.

Off the back of it, I wrote something for the item inventory in for Final Fantasy X. On the github main.lua I found that memory records have a DontSave boolean. So this creates 200+ entries at "run time" that aren't written back to the CT file.

http://forum.cheatengine.org/viewtopic.php?p=5670288#5670288

Here's a snippet that might help inspiration for others, it creates child entries under a pre-defined group header called "Items".

I couldn't find a way of deleting the child records, which would be handy clean up when running the function multiple times. Also couldn't find a way to create Group Headers either.

What would be really neat is to have the LUA executed by expanding the Group Header in the table to create the child entries on the fly then.

Code:
local item_table = {
  [0]="Potion",
  [1]="Hi-potion",
  [2]="X-potion",
  --- truncated
  [109]="Gambler's Spirit",
  [110]="Underdog's Secret",
  [111]="Winning Formula",
}

local droplist = "255:NULL\n"
for k,v in pairs(item_table) do
  droplist = droplist .. k + 8192 .. ":" .. v .. "\n"
end

local itemCount = 150
local quantity_base = "FFX.exe+D30B5C"
local type_base = "FFX.exe+D3095C"

local addr_list = getAddressList()
local group = addr_list.getMemoryRecordByDescription("Items")
for i=0, itemCount -1 do
    local slot_number = i+1
    -- Item Type with dropdown
    local slot_type = addr_list.createMemoryRecord()
    slot_type.setDescription("Slot " .. slot_number .. " Type")
    slot_type.setAddress(type_base .. "+2*" .. string.format( '%x', i))
    slot_type.DontSave = true
    slot_type.Type = vtWord
    slot_type.appendToEntry(group)
    slot_type.DropDownList.Text = droplist
    -------- Options ----
    slot_type.DropDownReadOnly=true  ---Disallow manual user input
    slot_type.DropDownDescriptionOnly=false  ----Only show the description part
    slot_type.DisplayAsDropDownListItem=true  ---Make the record display values like the dropdownlist
    -- Item Quantity
    local slot_quantity = addr_list.createMemoryRecord()
    slot_quantity.setDescription("Slot " .. slot_number .. " Quantity")
    slot_quantity.setAddress(quantity_base .. "+" .. string.format( '%x', i))
    slot_quantity.DontSave = true
    slot_quantity.Type = vtByte
    slot_quantity.appendToEntry(group)
end
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Thu May 19, 2016 4:53 pm    Post subject: Reply with quote

It would be nice if DB made the DropDownList property writable, such that we can assign the same stringlist to multiple memory records. That way, when you update one, the others will be updated as well.

I made a function that will forcefully do this, but I'm not sure if it has any other unintended side effects. It will probably break with any future versions of CE, but I figure whoever cares enough about this stuff will be able to figure out the new offsets themselves.
Code:
--[[
  memrec - the memory record to update
  strlist - the string list to assign to the memory record's DropDownList property
  destroy (opt) - indicates whether or not it should destroy the overwritten stringlist. This can cause memory access violations if there are any references to the string list still around (i.e. another memory record is also using this string list).
]]
function setDropDownList(memrec, strlist, destroy)
  assert(memrec and memrec.ClassName == "TMemoryRecord", "invalid memrec")
  assert(strlist and strlist.ClassName == "TStringList", "invalid strlist")

  local oldList
  if destroy then oldList = memrec.DropDownList end

  if cheatEngineIs64Bit() then
    local recBase = assert(readQwordLocal(tostring(memrec):match("%x+$")), "Could not read userdata")
    local strBase = assert(readQwordLocal(tostring(strlist):match("%x+$")), "Could not read userdata")
    assert(readStringLocal(readQwordLocal(readQwordLocal(readQwordLocal(recBase+0x90))+0x18)+0x1, 11) == "TStringList", "memrec offset 0x90 is not TStringList")
    assert(readStringLocal(readQwordLocal(readQwordLocal(strBase)+0x18)+0x1, 11) == "TStringList", "invalid strlist")
    writeQwordLocal(recBase+0x90,strBase)
  else
    local recBase = assert(readIntegerLocal(tostring(memrec):match("%x+$")), "Could not read userdata")
    local strBase = assert(readIntegerLocal(tostring(strlist):match("%x+$")), "Could not read userdata")
    assert(readStringLocal(readIntegerLocal(readIntegerLocal(readIntegerLocal(recBase+0x54))+0xC)+0x1, 11) == "TStringList", "memrec offset 0x54 is not TStringList")
    assert(readStringLocal(readIntegerLocal(readIntegerLocal(strBase)+0xC)+0x1, 11) == "TStringList", "invalid strlist")
    writeQwordLocal(recBase+0x54,strBase)
  end

  if oldList then oldList.destroy() end  -- destroyed here just in case CE tries to access the DropDownList while this is assigning the new list
end

I was sad to figure out that CE saves the text and attributes of the drop down lists on a per memory record basis, so this won't actually help anyone save disk space. Hopefully someone can still make use of it, though.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Rhagic
Advanced Cheater
Reputation: 4

Joined: 23 Aug 2011
Posts: 94

PostPosted: Fri May 20, 2016 4:47 am    Post subject: Reply with quote

ParkourPenguin wrote:
I was sad to figure out that CE saves the text and attributes of the drop down lists on a per memory record basis, so this won't actually help anyone save disk space. Hopefully someone can still make use of it, though.


Thank you.

Actually, it could help. I've started populating the memory records using LUA and not having them saved back to the CT file with:

Code:
rec.DontSave = true
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites