|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
WeaMas How do I cheat? Reputation: 0
Joined: 29 Jan 2018 Posts: 4
|
Posted: Mon Jan 29, 2018 10:31 am Post subject: Help programming interactivity into infinite loop |
|
|
I'm trying to write a LUA script to help search through bones data in DOA5 to make life easier than staring at a memory map and losing track of my place all the time. The problem is, I have no clue how to code user interactivity into a script.
I have shoved my code in a while(true) loop, I think I have a way to break the loop, but when I execute the infinite loop just causes cheat engine to say not responding. I've tried using a delay() to have the loop execute once a second, but still causes "not responding".
Code: | BaseAddress = "46566e80"
VectorSize = 3
NumVectors = 3
Indicies = VectorSize * NumVectors
Offset = 0
AddressTable = {}
FloatTable = {}
UpdateAddress = 1
openProcess("game.exe")
while(true) do
if(UpdateAddress)
then
for i = 1,Indicies
do
AddressTable[i] = BaseAddress .. "+" .. 4*(i-1) .. "+" .. Indicies*Offset*4
FloatTable[i] = readFloat(AddressTable[i])
print(FloatTable[i])
end
UpdateAddress = 0
end
if(isKeyPressed(VK_NUMPAD6))
then
Offset = Offset+1
UpdateAddress = 1
end
if(isKeyPressed(VK_NUMPAD4))
then
Offset = Offset-1
UpdateAddress = 1
end
if(isKeyPressed(VK_SUBTRACT))
then
break
end
--break
end |
This is my skeleton code that I'm working with right now, if I don't uncomment the final break then my script gets stuck in the infinite loop. Some guidance would be nice, the stickied tutorials don't deal with interactivity or how to make your script not take up 100% cpu time.
|
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Mon Jan 29, 2018 11:35 am Post subject: |
|
|
Yeah lua scripts are ran in the same thread as the GUI by default so an infinite loop is going to freeze things, similarly having the code constantly looping is going to eat the CPU
The solution is to A) use a thread and B) "sleep" so the processor can run a different thread for awhile
Code: | createThread(function()
while true do
... -- do whatever
sleep(100)
end
end) |
btw, you'll probably want to check input before using it (Offset/UpdateAddress), that way the user doesn't change press a key and then have to wait 100 milliseconds or whatever your loop's delay is before it actually takes affect.
Oh, and 0 is considered "true" in lua, eg. if 0 then print('hi') end will print "hi". Use the boolean values true and false (my preference) or explicitly check == 1 / ~= 0 / not (... == 0). You can also use nil instead of false but that can have unintended effects, particularly with tables, since it's the implicit value for anything not given a value.
|
|
Back to top |
|
|
WeaMas How do I cheat? Reputation: 0
Joined: 29 Jan 2018 Posts: 4
|
Posted: Mon Jan 29, 2018 3:38 pm Post subject: |
|
|
Is there any quick reference you can link for createThread()? I've looked through the Lua 5.3 reference and I only see coroutine.create() for threads, and it looks significantly more complicated to use.
0 acting as true makes me a little bit peeved if that's true. I had a little bit of experience in C++ before trying to do this and I'm used to 0 being cast as false (although my textbook made sure to state many times that False != 0).
And yeah, I know that I'd probably want to check for input first before running any code, I just wanted to get the most important parts of the code up and working before I organized. I actually had to debug the address and float tables for a while because I didn't realize that readFloat doesn't read decimal. Is there a way to get it to read decimal/integers properly?
|
|
Back to top |
|
|
TheyCallMeTim13 Wiki Contributor Reputation: 50
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Mon Jan 29, 2018 4:19 pm Post subject: |
|
|
createThread is added by Cheat Engine, The wiki is an ok place to check (no thread class yet) but the best place is the "celua.txt" text file in the CE folder.
And yeah, I just tend to try and be more explicit, you tend to find a lot of odd ball behavior in a verity of languages. So less duck typing and more direct checks. But I think in Lua and some others any thing that's not false, nil, or none is true.
WeaMas wrote: | ... readFloat doesn't read decimal. Is there a way to get it to read decimal/integers properly? |
Not sure what you mean, but "readFloat" just reads the bytes at a given address as a single precision floating point and returns a Lua number object, in Lua there are no decimal types and all numbers are in decimal format. Maybe "readInteger" is what you need.
_________________
|
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Mon Jan 29, 2018 4:36 pm Post subject: |
|
|
Hm, apparently the only place it's documented for lua is in the celua.txt file in the CE install directory, while the built-in help has a lot I don't see it there (just the createThread of AA code, same purpose essentially, just assembly not lua), nor is it mentioned on the wiki (TheyCallMeTim13 has been updating it lately). I've pasted the documentation below.
Yeah, there are a couple things like that in lua, for example tables start at 1. While you can put things in index 0, things like ipairs will skip it. In a way I applaud Lua for not doing something just because that's how some other language did it, but it can cause a couple issues if you don't realize that there can be differences. (note: many CE functions return userdata objects that start at 0, but a few do return lua tables that start at 1, so... yeah lol)
Also false is 0, though for things that return a failure code 0 is probably "success" so that actual values can be used for looking up actual error messages. That's different from false not being 0. A "true" value however can be any non-zero value, though the explicit true macro/keyword is almost always 1; As are normalized booleans which I believe C++ forces on assignment now, essentially equivalent to !!((bool)x).
readFloat should read decimals, readInteger exists but it won't read a floating point value in the way one might hope for. Once you've read a float you can use math.floor / ceil / round to make it an integer.
Code: | Thread Class: (Inheritance: Object)
createThread(function(Thread,...), ...) :
Executes the given function in another thread using the systems thread mechanism
The function returns the Thread class object
function declaration: function (Thread, ...)
createThreadSuspended(function(Thread,...), ...) :
Same as createNativeThread but it won't run until resume is called on it
properties
name: string - This name will be shown when the thread terminated abnormally
Finished: boolean - Returns true if the thread has reached the end. Do not rely on this if the thread is freeOnTerminate(true) (which is the default)
Terminated: boolean - Returns true if the Terminate method has been called
methods
freeOnTerminate(state) :
When set to true the thread object will free itself when the function ends (default=true)
Note: Use this only from inside the thread function as the thread might have already terminated and freed itself when called
synchronize(function(thread, ...), ...) :
Called from inside the thread. This wil cause the tread to get the main thread to execute the given function and wait for it to finish.
Usually for GUI access
Returns the return value of the given function
waitfor() :
Waits for the given thread to finish (Not recommended to call this from inside the thread itself)
suspend() :
Suspend the thread's execution
resume() :
Resume the thread;s executionmm
terminate() :
Tells the thread it should terminate. The Terminated property will become true
|
|
|
Back to top |
|
|
WeaMas How do I cheat? Reputation: 0
Joined: 29 Jan 2018 Posts: 4
|
Posted: Mon Jan 29, 2018 5:02 pm Post subject: |
|
|
I should have been more specific when I asked if readFloat could read integers or decimal. I meant instead of the address of the float to be read being formatted as hex (46566e80 in my example code), the address could be converted to a decimal number (0x46566e80 => 1180069504). It's just easier to work with integers than to treat the addresses as strings.
The original problem I was having was just that, I formatted all hex values as integers and then put them into readFloat, which obviously caused them to return nil because it's way out of bounds when read as a hexadecimal input.
|
|
Back to top |
|
|
TheyCallMeTim13 Wiki Contributor Reputation: 50
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Mon Jan 29, 2018 5:10 pm Post subject: |
|
|
readFloat
readFloat takes integers or strings for the address.
Code: | local flt = readFloat(1180069504) |
Code: | local flt = readFloat(0x46566E80) |
Code: | local flt = readFloat('46566E80') |
Code: | local flt = readFloat('[[00123ABC]+4]+18') |
But numbers in address strings are interpreted as hexadecimal.
You can use "getAddress" to just return the integer value. getAddress
_________________
|
|
Back to top |
|
|
WeaMas How do I cheat? Reputation: 0
Joined: 29 Jan 2018 Posts: 4
|
Posted: Mon Jan 29, 2018 5:51 pm Post subject: |
|
|
I'm getting it to work now, odd. I think before I was trying to reference the AddressTable in the readFloat function by doing:
Code: | FloatTable.i = readFloat(AddressTable.i) |
So you can't use variables/index in the dot notation for arrays?
Last edited by WeaMas on Mon Jan 29, 2018 6:09 pm; edited 1 time in total |
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Mon Jan 29, 2018 5:59 pm Post subject: |
|
|
AddressTable.i is equivalent to addressTable['i'] (string/hash table) not addressTable[i] (number/array), which is not the same as addressTable[tostring(i)]
example
Code: | local i = 123
local AddressTable = {}
AddressTable.i = "I'm I!"
AddressTable[i] = "No I'm i!"
--AddressTable['i'] = "I'm really I too!"
AddressTable[tostring(i)] = 'I wanna be i!'
for k,v in pairs(AddressTable) do
print(k,'-', type(k),'-', v)
end | result Code: | 123 - string - I wanna be i!
i - string - I'm I!
123 - number - No I'm i!
-- uncommented
123 - string - I wanna be i!
i - string - I'm really I too!
123 - number - No I'm i!
|
edit: note that lua strings in lua are immutable (so you can't change a string, only create a new one) but lua will check if the string already exists in memory before recreating it. So two strings with the same content will be equal, unlike C where strings can have the same content but be in different memory locations and so compare as different because the pointers are different.
Tables however are much like you might think of strings
Code: | local AddressTable = {}
local oneString = 'Hello World!'
local multiple = 'Hello' .. " World" .. '!'
AddressTable[oneString] = 1
AddressTable[multiple] = 2
AddressTable[multiple .. '1'] = 3
for k,v in pairs(AddressTable) do
print(k,'-', type(k),'-', v)
end
print(('-'):rep(30))
local t1 = {['cat']=1,['dog']=2}
local t2 = {['cat']=1,['dog']=2}
local t3 = t1 -- reference
t3.cat = 5
t3.dog = 32
t3.answer = 42
AddressTable[t1] = 'catdog!'
AddressTable[t2] = 'dogcat!'
AddressTable[t3] = 'what?'
for k,v in pairs(AddressTable) do
-- answer index from key, if it exists
local answer = type(k) == 'table' and k.answer
print(tostring(k),'-', type(k),'-', v, answer)
end
print(tostring(AddressTable[tostring(t1)])) | result Code: | Hello World!1 - string - 3
Hello World! - string - 2
------------------------------
Hello World!1 - string - 3
table: 00000000033156F0 - table - dogcat!
table: 00000000033156B0 - table - what? 42
Hello World! - string - 2
nil |
edit: oh, and like tostring(i) is different from i, AddressTable[t1] is not the same as AddressTable[tostring(t1)], just to cover that potential case as well
|
|
Back to top |
|
|
|
|
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
|
|