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 


Using timers/loops properly [solved]

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
b0g_
How do I cheat?
Reputation: 0

Joined: 22 Jan 2022
Posts: 5

PostPosted: Tue Jan 25, 2022 9:27 am    Post subject: Using timers/loops properly [solved] Reply with quote

I'm currently trying to figure out how to properly use createTimer to loop some code when a table entry is toggled. What I have is this:

Code:

{$lua}

[ENABLE]

if not timer then
   timer = createTimer(nil)
   timer.OnTimer = function(timer)
                   --code here
                 end
   timer.Interval = 250 --delay
   timer.Enabled = true
else
    timer.Enabled = true
end

[DISABLE]

if (timer) then
   timer.Enabled = false
end


It works *almost* perfectly, once the entry is toggled it starts looping and once disabled it stops.

Now the issue here is that I have to change the timer name for every different entry, or else it will just do timer.Enabled on the timer that was first initialised.

I'm wondering if I could make a private timer just for the entry, that can't be referenced from a different one, so that I can just copy paste the script for all the cheats that need a loop when toggled.

Or even better is there a completely different way that can achieve that effect without using timers or what I'm currently doing. Thanks in advance!


Last edited by b0g_ on Tue Jan 25, 2022 3:20 pm; edited 1 time in total
Back to top
View user's profile Send private message
LeFiXER
Grandmaster Cheater Supreme
Reputation: 20

Joined: 02 Sep 2011
Posts: 1055
Location: 0x90

PostPosted: Tue Jan 25, 2022 9:46 am    Post subject: Reply with quote

Try this:
Code:

if not timer then
   -- Good practice to ensure that the object has a parent, that way if anything erroroneous happens with the object a memory leak isn't created
   -- because it can be destroyed when the parent is destroyed i.e. closed/terminated.
   local timer = createTimer(getMainForm(), true)
         timer.Interval = 250 --delay
         timer.OnTimer = function(timer)
                           --code here
                         end
else
    timer.Enabled = true
end

[DISABLE]

if timer then
   timer.Enabled = false
end


You created timer as a global object rather than a private one (local), with the necessary changes you should yield the desired results.
Back to top
View user's profile Send private message
b0g_
How do I cheat?
Reputation: 0

Joined: 22 Jan 2022
Posts: 5

PostPosted: Tue Jan 25, 2022 10:09 am    Post subject: Reply with quote

Okay so I tried your code hoping that was the answer but when enabling the entry it seems to create a new timer every time and when disabling the entry it doesn't stop the old timer.

Here's the code, I'm using print to see when the code is being executed:

Code:

{$lua}

[ENABLE]

if not timer then
   local timer = createTimer(getMainForm(), true)
         timer.Interval = 250 --delay
         timer.OnTimer = function(timer)
                           --code here
                           print('test')
                         end
else
    timer.Enabled = true
end

[DISABLE]

if timer then
   timer.Enabled = false
end


I forgot to mention in the post that I had also tried using local but at the time I thought I was using it wrong but since it means that the timer is created locally I literally have no idea why this is happening...
Back to top
View user's profile Send private message
Frouk
Master Cheater
Reputation: 5

Joined: 22 Jun 2021
Posts: 489
Location: mov dword ptr [Ukraine]

PostPosted: Tue Jan 25, 2022 11:15 am    Post subject: Reply with quote

i don't think thats
Code:
if timer then timer.destroy() timer = nil end

will work for local timers (the disable part won't do anything to timer since it created in enable section only)

_________________
void(__cdecl *Haxing)(HWND hGameWindow)
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Tue Jan 25, 2022 1:24 pm    Post subject: Reply with quote

b0g_ wrote:
Now the issue here is that I have to change the timer name for every different entry, or else it will just do timer.Enabled on the timer that was first initialised.
That's how global variables work. The easiest solution is to use a unique global name for each timer.

If you really don't want to do that, use the ID of the memory record to index into a global table that contains the timers:
Code:
{$lua}
if syntaxcheck then return end
if not scriptTimers then scriptTimers = {} end

[ENABLE]

local id = memrec.ID
local t = scriptTimers[id]

if t then
  t.Enabled = true
else
  t = createTimer()
  t.Interval = 250
  t.OnTimer = function()
    -- code
  end
  scriptTimers[id] = t
end

[DISABLE]

local t = scriptTimers[memrec.ID]
if t then
  t.Enabled = false
end


You can also make the timers local and have them try to automatically disable themselves:
Code:
[ENABLE]
{$lua}
if syntaxcheck then return end

local t = createTimer()
t.Interval = 250
t.OnTimer = function(t)
  if not memrec.Enabled then
    t.Enabled = false
    return
  end
  -- code
end
{$asm}
[DISABLE]
This has a more generic version of the ABA problem: if the timer is disabled and enabled again between timer invocations, multiple instances of the timer will be running.
You could solve this by introducing a counter that keeps track of which invocation the script is running in, store that in a global, and use it in the OnTimer function; however, you'd have the same problem with that global variable as you do now.

_________________
I don't know where I'm going, but I'll figure it out when I get there.


Last edited by ParkourPenguin on Tue Jan 25, 2022 3:35 pm; edited 1 time in total
Back to top
View user's profile Send private message
b0g_
How do I cheat?
Reputation: 0

Joined: 22 Jan 2022
Posts: 5

PostPosted: Tue Jan 25, 2022 2:11 pm    Post subject: Reply with quote

ParkourPenguin wrote:
Code:
{$lua}
if syntaxcheck then return end
if not scriptTimers then scriptTimers = {} end

[ENABLE]

local id = memrec.ID
local t = scriptTimers[id]

if t then
  t.Enabled = true
else
  t = createTimer()
  t.Interval = 250
  t.OnTimer = function()
    -- code
  end
end

[DISABLE]

local t = scriptTimers[memrec.ID]
if t then
  t.Enabled = false
end


Outstanding, It seems to now work perfectly however I did have to make a small change to createTimer because it wasn't working when done directly to the variable t

So I now have a perfect timer that can be copy/pasted without changes since everything is local to the memrec.
Here you go if anyone needs it:

Code:

{$lua}
if not scriptTimers then scriptTimers = {} end

local function onTimer(timer)

--code

end

[ENABLE]

local id = memrec.ID
local t = scriptTimers[id]

if t then
  t.Enabled = true
else
  scriptTimers[id] = createTimer() --changes I made
  t = scriptTimers[id]
  t.Interval = 250
  t.OnTimer = onTimer
end

[DISABLE]

local t = scriptTimers[memrec.ID]
if t then
  t.Enabled = false
end
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Tue Jan 25, 2022 3:35 pm    Post subject: Reply with quote

Right, my bad, forgot this line:
Code:
scriptTimers[id] = t

_________________
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
paul44
Expert Cheater
Reputation: 2

Joined: 20 Jul 2017
Posts: 152

PostPosted: Thu Mar 21, 2024 12:05 pm    Post subject: get a list/status of running timers ? Reply with quote

^ I really liked the idea about managing timers via a table. you can then easily show their current status.

However: I also use "instant_kill" timers, primarily for auto-closing scripts. Meaning: upon enabling, the script checks if prerequisites are met (eg pointers/values needed to be populated); and if not, just disables the script (and instructing user what to do next).
When something goes wrong - like game crashing Embarassed - the timer does not get destroy()-ed; and will (probably) remain running its own instance till one quits the table ?!
=> if so, is there a way to show currently active/instantiated timer(objects) ?

------------------------
show current timers:

[code] local aTimer = { [99889922] = 'System', [88619] = 'Free Roam' }

local sTimer = ''
for k,v in pairs(scriptTimers) do
local sName = aTimer[k]
local sRun = 'OFF'
if (v.enabled) then sRun = 'ON ' end
local sID = string.sub(string.format('[%s]%s',tostring(k),string.rep(" ",10)),1,10)

sTimer = sTimer .. string.format('%5s - %s - %s',sRun,sID,sName) .. '\n'
--print(sTimer)
end

showMessage(sTimer)[/code]
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