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 


Simple Coroutine Example

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> LUA Tutorials
View previous topic :: View next topic  
Author Message
atom0s
Moderator
Reputation: 155

Joined: 25 Jan 2006
Posts: 7977
Location: 127.0.0.1

PostPosted: Sun Jun 28, 2020 7:36 pm    Post subject: Simple Coroutine Example Reply with quote

Since this came up in a recent topic, here is an example of using Lua's built-in coroutine functionality. This is using a CE timer as a means to resume the coroutine as needed. (This is a way to do intensive work without freezing the CE UI until things have fully finished.)

This is a very basic example showing the bare minimum of doing something with coroutines. They are extremely flexible and great to use for a lot of things, so I'd encourage people to get familiar with them more since they are generally not used much by less advanced users of Lua.

Code:

-- CE Coroutine Example
-- by atom0s

--[[
    Flag used to determine if the coroutine should continue running.
   
    This is used to tell the coroutine if it should continue working or not. You can set this internally within the coroutine after it has
    completed its work, or you can use something else as a way to 'timeout' the coroutine to stop it from endlessly running if it failed
    it's objective. (Make a second timer that has a 10 second interval delay and just set isRunning = false and kill that new timer for example.)
]]--
local isRunning = true;

--[[
    Create the coroutine that will do the heavy lifting work.
   
    This coroutine SHOULD NOT do any intensive/long loops. You should be coding this to do a single-attempt fire at what your objective/goal is
    in order to allow the yielding to properly work and let CE continue to operate without freezing.
   
    For example, if you are scanning for an AoB endlessly until it is found then you should not do a loop for it here. Instead, you should code
    the scan to happen once here. If not found, allow the coroutine.yield() call to happen. If found, set isRunning to false and return early and
    the coroutine will die cleanly on the next timer tick itself.
]]--
local co = coroutine.create(function()
    -- Check if isRunning is false..
    while (isRunning == true) do
        -- Do your single-tick of work here..
        print('coroutine tick!');
       
        -- Yield the coroutine until it's resumed again via our timer..
        coroutine.yield();
    end
   
    -- Coroutine has completed, it will be marked as dead after this print..
    print('coroutine has completed!');
end);

--[[
    Create the timer to tick the coroutine.
   
    This timer is used to resume the coroutine each time the timer interval happens. For intensive workloads, you can just set this timers
    interval to something really low (ie. 1 to 10) to ensure it is operating fast. The timer will continue to check the status of the coroutine
    each tick until it is either nil or marked as dead. (Meaning it returned without yielding.) Once the coroutine is dead, the timer will kill
    itself and cleanup.
]]--
local timer     = createTimer();
timer.Interval  = 500; -- Can adjust to a much smaller interval if you need faster ticks of the coroutines work..
timer.OnTimer   = function(t)
    print('timer tick!');

    -- Check and resume the coroutine each time the ticker ticks if the coroutine is valid..   
    local status = coroutine.status(co);
    if (co ~= nil and status ~= 'dead') then
        coroutine.resume(co);
    else
        -- Kill the timer if the coroutine has died..
        t.destroy();
        print('timer has been destroyed!');
    end
end;

--[[
    Creates an example hotkey as a means of 'canceling' the coroutine.
   
    This is just to demonstate how to kill the coroutine outside of the coroutine and timer functions via the isRunning flag.
    Think of this like a 'Cancel' button.
]]--
createHotkey(function()
    print('hotkey was pressed!');
   
    -- Tell the coroutine to finish..
    isRunning = false;
end, VK_F2);


This will create a coroutine that is continuously resumed by a timer every 500ms.
You can press F2 to exit the coroutine which will self-kill the timer.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> LUA Tutorials 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 cannot download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites