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 


How to read/write name of character?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 202

PostPosted: Sun Aug 12, 2018 9:43 am    Post subject: How to read/write name of character? Reply with quote

How to read name from address to Edit box? For example: name of character consist from 12 bytes (12 letters/symbols) . Each 1 letter is 1 byte. If 1 byte value == 0x21 then it is "A", or if == 0x41 then it is "a".
Code:

  Namestbl = {
 [0x21] = 'A'
,[0x22] = 'B'
,[0x23] = 'C'
,[0x24] = 'D'

,[0x41] = 'a'
,[0x42] = 'b'
,[0x43] = 'c'

,[0x00] = ' ' -- SPACE
}


How to write name from Edit box to address?
If we need to write name from Edit box, then after letters other bytes must be filled with 0xFF. For example: If we typed 3 letters "B","C","D", other 9 bytes must be written with 0xFF. Then 12 bytes should be written like this: 0x22, 0x23, 0x24, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF ,0xFF, 0xFF.
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Sun Aug 12, 2018 10:25 am    Post subject: Reply with quote

Code:
readString(address, maxlength, widechar OPTIONAL) : Reads a string till it encounters a 0-terminator. Maxlength is just so you won't freeze for too long, set to 6000 if you don't care too much. Set WideChar to true if it is encoded using a widechar formatting

writeString(address,text, widechar OPTIONAL) : Write a string to the specified address. Returns true on success

source: celua.txt (though it's on the wiki as well https://wiki.cheatengine.org/index.php?title=Lua:readString)

Since it's 1 character per byte it's not a wide string so you could either pass false or just pass two and let it implicitly be nil which is a false expression.


Looks like if you don't pass maxlength to readString it defaults to 50 ([url=https://github.com/cheat-engine/cheat-engine/blob/d218638b19a67d74cb32a6c313bfa022da1984b1/Cheat%20Engine/LuaHandler.pas#L1598-L1601]github]), looked it up since I often don't but that didn't say it's optional like widechar Smile

Code:
As for the edit box
Edit Class: (Inheritance: WinControl->Control->Component->Object)
createEdit(owner): Creates an Edit class object which belongs to the given owner. Owner can be any object inherited from WinControl

properties
  Text: string - The current contents of the editfield
...


so FormName.EditName.Text, eg. CETrainer.EditBox1.Text, is the text/name in the edit box and you'd just add = somestring or = readString(... args) to set it.

edit: just saw the 0xFF/255/-1... that's strange, typically strings just end with a 0 byte (or two for wide strings). But easy enough I suppose (assuming addr is a number)
For reading you can use eg. readString(addr,12):gsub('\xFF','') to remove the 0xFF bytes.
for writing you could use writeString(addr,newname .. ('\xFF'):rep(12-#newname)) to concatenate the needed bytes (or use two writeStrings to prevent the concatenation but with only 12 bytes it probably doesn't matter that lua strings are immutable and concatenating requires 2x the memory)

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Sun Aug 12, 2018 11:44 am    Post subject: Reply with quote

That's a different character encoding. Seems like it's offset by -0x20 from ASCII.

I can't post example code because cloudfare thinks it's evil and CEF fails when posting is interrupted, but the code isn't too complicated. Use readBytes / writeBytes to deal with the game's memory and string.char / string.byte to convert between numbers and strings. table.concat and string.gmatch may also be useful.

_________________
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
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 202

PostPosted: Sun Aug 12, 2018 12:25 pm    Post subject: Reply with quote

Tried with readString, but without result. Or I do not know, how to work with readString. Found a solution for "read character's name" and it works:
Code:
Namestbl = {
 [0x21] = 'A'
,[0x22] = 'B'
,[0x23] = 'C'
,[0x24] = 'D'

,[0x41] = 'a'
,[0x42] = 'b'
,[0x43] = 'c'

,[0x00] = ' ' -- SPACE
}

local n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12 = readBytes(0x009E8634,12)

  UDF1.CEEdit505.Text = Namestbl[n1]..Namestbl[n2]..Namestbl[n3]..Namestbl[n4]
  ..Namestbl[n5]..Namestbl[n6]..Namestbl[n7]..Namestbl[n8]..Namestbl[n9]
  ..Namestbl[n10]..Namestbl[n11]..Namestbl[n12]


But can not find solution to write name from Edit box.Trying next code, but it did not works:
Code:
for x = 0, 8 do
  local currentCharNames = CharNames[x+1]
  local offset1 = x * 0x84

  CharNames[x+1].OnKeyPress = function(sender, key)
      timer.Enabled = false
      local a = sender.Text
      if (a~=nil) and isKeyPressed(VK_RETURN) then

        writeBytes(0x009E8634 + offset1, Namestbl[currentCharNames.Text[1]],Namestbl[currentCharNames.Text[2]])
        timer.Enabled = true
      end
      return key
    end
end


Last edited by Razi on Tue Aug 14, 2018 3:33 am; edited 1 time in total
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Sun Aug 12, 2018 4:33 pm    Post subject: This post has 1 review(s) Reply with quote

Quote:
That's a different character encoding. Seems like it's offset by -0x20 from ASCII.
Ah, so it is. Perhaps something like this then

Code:
local function readName(addr, len)
  len = len or 12 -- defaults to 12
  local bytes = readBytes(addr, len, true)
  local chars = {}
  for k,v in ipairs(bytes) do
    if v == 0xFF then break end
    chars[#chars+1] = string.char(v+0x20)
  end
  return table.concat(chars,'')
end

local function writeName(addr, name, len)
  len = len or 12 -- default to 12
  assert(#name < len, 'Name must be less than len (default 12)')
  local bytes = {}
  for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end
  for i=1,len-#bytes do bytes[#bytes+1] = 0xFF end -- pad with 0xFF
  writeBytes(addr, bytes)
end

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 202

PostPosted: Mon Aug 13, 2018 3:32 am    Post subject: Reply with quote

FreeER wrote:
Ah, so it is. Perhaps something like this then

Functions: readName and writeName, they work great, thank you very much.

Quote: "If we need to write name from Edit box, then after letters other bytes must be filled with 0xFF". I made a mistake, sorry.
This works in the game like this: If we need to write name from Edit box, then after letters first 2 bytes must be filled with 0xFF, and last 3 bytes must be filled with 0xFF. Bytes between first 2 bytes and last 3 bytes must be filled wih 0x00.

For example:
If we typed 3 letters "A","A","A". Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0xFF, 0xFF, 0x00, 0x00 , 0x00, 0x00, 0xFF ,0xFF, 0xFF.
Or 5 letters: AAAAA. Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0xFF, 0xFF, 0x00, 0x00, 0xFF ,0xFF, 0xFF.
Or 7 letters: AAAAAAA. Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0xFF , 0xFF , 0xFF ,0xFF, 0xFF.
So, only if letters 7 or more, then other bytes must be filled with 0xFF.

Can you change the function: local function writeName(addr, name, len) , to write bytes as in the examples?
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Mon Aug 13, 2018 7:06 am    Post subject: Reply with quote

strange but simple enough I suppose.

Code:
local function writeName(addr, name, len)
  len = len or 12 -- default to 12
  assert(#name < len, 'Name must be less than len (default 12)')
  local bytes = {}
  for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end
 
  -- add 0xFF 0xFF 0x00 ... 0xFF 0xFF 0xFF, as possible
  if len - #bytes > 5 then
    bytes[#bytes+1] = 0xFF; bytes[#bytes+1] = 0xFF  -- starting 0xFFs
  end
  if len - #bytes > 3 then -- if more room than last 3 0xFFs take fill with 0x0s
      for i=#bytes,len-3 do bytes[#bytes+1] = 0 end
  end
  for i=#bytes,len do bytes[#bytes+1] = 0xFF end -- end with 0xFFs
 
  writeBytes(addr, bytes)
end


What if you had 8-12 letters (where you don't have room for the starting 2 and ending 3, edge cases matter as far as correctness)? ^ should just fill with 0xFFs in those cases (well, if the assert was changed to <= rather than < for 12) so hopefully that's correct, or simply not an issue in your case lol

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 202

PostPosted: Mon Aug 13, 2018 8:07 am    Post subject: Reply with quote

FreeER wrote:
should just fill with 0xFFs in those cases

Yes, if 7-11 letters, then other bytes after letters should be filled with 0xFF. Example: If 10 letters: "A", then should be like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 00x21, 0x21, 0xFF, 0xFF. Or if 11 letters: "A", then 12 bytes should be written like this: eleven 0x21, and one 0xFF.
(Maximum 11 letters for name, because after letters should be at least one 0xFF)

New function writeName does not work correctly. I altered it a bit. Now it works as was needed.
Code:
local function writeName(addr, name, len)
  len = len or 12 -- default to 12
  assert(#name < len, 'Name must be less than len (default 12)')
  local bytes = {}
  for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end

  -- add 0xFF 0xFF 0x00 ... 0xFF 0xFF 0xFF, as possible
  if len - #bytes > 1 then
    bytes[#bytes+1] = 0xFF; bytes[#bytes+1] = 0xFF  -- starting 0xFFs
  elseif len - #bytes == 1 then
    bytes[#bytes+1] = 0xFF
  end
  if len - #bytes > 3 then -- if more room than last 3 0xFFs take fill with 0x0s
      for i=#bytes,len-3 do bytes[#bytes+1] = 0 end
  end
  for i=#bytes,len do bytes[#bytes] = 0xFF end -- end with 0xFFs

  writeBytes(addr, bytes)
end
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 Lua Scripting 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