We have detected that cookies are not enabled on your browser. Please enable cookies to ensure the proper experience.
Results 1 to 4 of 4
  1. #1

    Question how to write a timer?

    Hey all, sorry if this is the wrong forum to post it in, seemed like the closest (or at least most active) part of the Lua scripting forums for my question.

    I'm writing my first plugin, and I'm still quite a newbie when it comes to programming in general (no formal training) but I've been able to nearly finish my plugin until I ran into a problem trying to write a timer. Essentially I'm trying to write a simple timer that will call a function, wait 60 seconds, and then call another function. I've tried a few ways to get this to work using Turbine.Engine.GetGameTime(), something along the lines of:
    Code:
    function timer(duration,startTime)
        local completed = false
        local timestamp = Turbine.Engine.GetGameTime()
        if timestamp >= startTime + duration then
            completed = true
            return completed
            else
            timer(duration,startTime)
        end
    end
    curTime = Turbine.Engine.GetGameTime()
    if timer(60,curTime) == true then
            <do more stuff>
    end
    that particular one got " \Main.lua:199: stack overflow" but it was a bit of a shot in the dark to begin with

    I've also tried using while loops which crashed the client (such as: while timestamp <= duration do <stuff> timestamp = Turbine.Engine.GetGameTime() else <more stuff> )

    anyway, I'm wondering if there is a way to accomplish this that I'm not seeing,or maybe if there's a way to fix my nubby little code there to make it work.

    Thanks in advance
    -Iinferno
    [CENTER][COLOR=lightblue]Iinferno - r12 LM[/COLOR][COLOR=red] IVillKillU - r8 Reaver[/COLOR][COLOR=orange] Dongramorthil - Warden[/COLOR] [COLOR=Magenta]Doalin - Hunter [/COLOR][COLOR=#696969]​Defaelearin - RK [/COLOR][COLOR=#8b4513]Dongrailin - Captain [/COLOR][COLOR=#add8e6](Officer of Preying Mantis)[/COLOR]
    [SIZE=1][SIZE=2][COLOR=#00ff00]Author of[/COLOR][/SIZE][COLOR=#4b0082][SIZE=2] [URL="http://www.lotrointerface.com/downloads/info745-Lore-MasterDebuffHelper.html"]DebuffHelper[/URL][/SIZE]


    [/COLOR][/SIZE]
    [/CENTER]

  2. #2
    Join Date
    Mar 2007
    Posts
    1,182
    The simplest solution would be to use an Update event handler to compare the current game time to a desired game time. The reason you use the Update event is that it fires asynchronously, allowing you to check the time once every time a frame is rendered, preventing the endless loops you were encountering. A more robust solution is to use a Timer class which can be instantiated as many times as needed, will support the AddCallback/RemoveCallback mechanism and will thus allow triggering multiple events if needed:
    Code:
    function AddCallback(object, event, callback)
        if (object[event] == nil) then
            object[event] = callback;
        else
            if (type(object[event]) == "table") then
                table.insert(object[event], callback);
            else
                object[event] = {object[event], callback};
            end
        end
        return callback;
    end
    function RemoveCallback(object, event, callback)
        if (object[event] == callback) then
            object[event] = nil;
        else
            if (type(object[event]) == "table") then
                local size = table.getn(object[event]);
                for i = 1, size do
                    if (object[event][i] == callback) then
                        table.remove(object[event], i);
                        break;
                    end
                end
            end
        end
    end
    Timer = class( Turbine.UI.Control );
    function Timer:Constructor()
        Turbine.UI.Control.Constructor( self );
        self.EndTime=Turbine.Engine.GetGameTime();
        self.Repeat=false;
        self.SetTime=function(sender, numSeconds, setRepeat)
            numSeconds=tonumber(numSeconds);
            if numSeconds==nil or numSeconds<=0 then
                numSeconds=0;
            end
            self.EndTime=Turbine.Engine.GetGameTime()+numSeconds;
            self.Repeat=false; -- default
            self.NumSeconds=numSeconds;
            if setRepeat~=nil and setRepeat~=false then
                -- any non-false value will trigger a repeat
                self.Repeat=true;
            end
            self:SetWantsUpdates(true);
        end
        self.Update=function()
            if self.EndTime~=nil and Turbine.Engine.GetGameTime()>=self.EndTime then
                self:SetWantsUpdates(false); -- turn off timer to avoid firing again while we are processing (not likely but it's a good practice)
                -- fire whatever event you are trying to trigger
                if self.TimeReached~=nil then
                    if type(self.TimeReached)=="function" then
                        self.TimeReached();
                    elseif type(self.TimeReached)=="table"  then
                        for k,v in pairs(self.TimeReached) do
                            if type(v)=="function" then
                                v();
                            end
                        end
                    end
                end
                if self.Repeat then
                    self.EndTime=Turbine.Engine.GetGameTime()+self.NumSeconds;
                    self:SetWantsUpdates(true);
                end
            end
        end
    end
    -- somewhere else in code, you would instantiate an instance of the timer
    timer1=Timer();
    -- then set the TimeReached event handler
    myEvent=function()
        Turbine.Shell.WriteLine("Timer Just Fired!");
    end
    AddCallback(timer1,"TimeReached",myEvent)
    -- and finally, set the timer
    timer1:SetTime(60, true); -- cause the timer to fire every 60 seconds, auto repeating
    Ideally you would also call RemoveCallback(timer1,"TimeRea ched",myEvent) when your plugin unloads or the timer is no longer needed.

    EDIT: Fixed bug in Repeat code
    Last edited by Garan; Jul 16 2012 at 05:23 PM. Reason: typo

  3. #3
    thanks alot very helpful info. Game servers are still down so I can't try it quite yet but I'm pretty sure that's exactly what I needed.
    [CENTER][COLOR=lightblue]Iinferno - r12 LM[/COLOR][COLOR=red] IVillKillU - r8 Reaver[/COLOR][COLOR=orange] Dongramorthil - Warden[/COLOR] [COLOR=Magenta]Doalin - Hunter [/COLOR][COLOR=#696969]​Defaelearin - RK [/COLOR][COLOR=#8b4513]Dongrailin - Captain [/COLOR][COLOR=#add8e6](Officer of Preying Mantis)[/COLOR]
    [SIZE=1][SIZE=2][COLOR=#00ff00]Author of[/COLOR][/SIZE][COLOR=#4b0082][SIZE=2] [URL="http://www.lotrointerface.com/downloads/info745-Lore-MasterDebuffHelper.html"]DebuffHelper[/URL][/SIZE]


    [/COLOR][/SIZE]
    [/CENTER]

  4. #4
    Join Date
    Mar 2007
    Posts
    1,182
    Quote Originally Posted by dookie123 View Post
    thanks alot very helpful info. Game servers are still down so I can't try it quite yet but I'm pretty sure that's exactly what I needed.
    You're welcome. Note, there was a minor bug in the Repeat part of the code which I fixed after you posted so you probably should review the code you are using. The bug was that the line "if setRepeat~=nil and setRepeat~=false then" was incorrectly typed as "if setRepeat~=nil and self.Repeat~=false then" and the line "self.Repeat=setRepeat" should have been removed.

    I will be adding this sample to the Writing LotRO Lua Plugins for Noobs thread as it seems to be a worthy addition.
    Last edited by Garan; Jul 16 2012 at 06:30 PM.

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

This form's session has expired. You need to reload the page.

Reload