We have detected that cookies are not enabled on your browser. Please enable cookies to ensure the proper experience.
Results 1 to 6 of 6
  1. #1
    Join Date
    Jun 2009
    Posts
    1,371

    Lua: Wait command?

    Hey,

    I'm working on a plugin at the moment but need some advice. I've created a message box that asks a question with yes/no buttons to select. The function that creates the message box needs to return a string saying which button was pressed. What I need is some way to pause the script, like a wait command or something, so the plugin stops until one of the buttons is pressed. Otherwise it returns the default value.

    Any ideas please would be most appreciated. Thanks.
    Galuhad | Narvelan
    Evernight (formally of Eldar) | Plugins
    Kinship Revamp Proposal

  2. #2
    Join Date
    Jun 2009
    Posts
    1,371

    Re: Lua: Wait command?

    I found a possible solution in coroutines, but keep getting the message, "attempt to yield across metamethod/C-call boundary". Are coroutines disabled in Lotro?
    Galuhad | Narvelan
    Evernight (formally of Eldar) | Plugins
    Kinship Revamp Proposal

  3. #3
    Join Date
    Mar 2007
    Posts
    1,590

    Post Re: Lua: Wait command?

    There doesn't seem to be any way in LoTRO's version of Lua to yield processing. However, you can use the Update event handler to asynchronously handle responses. This usually means restructuring the code so that the part of the code before the dialog and the part after the dialog can be separated into two separate functions.

    Assuming you have a function that needs multiple sequential responses (this example uses 3) and you want to reuse the message box dialog, you would do something like:
    Code:
    SomeWindow.waitFlag=0;
    
    SomeWindow.SomeFunctionPart1=function()
        -- first part of code up to the first dialog
        SomeWindow.waitFlag=1;
    
        -- display dialog with first question text buttons
        SomeDialog.TextMsg:SetText("this is the first question");
        SomeDialog:SetVisible(true);
    end
    SomeWindow.SomeFunctionPart2=function()
        if SomeDialog:GetButtonString()=="string1" then
            -- button 1 code
        elseif SomeDialog:GetButtonString()=="string2" then
            -- button 2 code
        end
        -- other code
        SomeWindow.waitFlag=2;
        -- display dialog with second question text buttons
        SomeDialog.TextMsg:SetText("this is the second question");
        SomeDialog:SetVisible(true);
    end
    SomeWindow.SomeFunctionPart3=function()
        if SomeDialog:GetButtonString()=="string1" then
            -- button 1 code
        elseif SomeDialog:GetButtonString()=="string2" then
            -- button 2 code
        end
        -- other code
        SomeWindow.waitFlag=3;
        -- display dialog with third question text buttons
        SomeDialog.TextMsg:SetText("this is the third question");
        SomeDialog:SetVisible(true);
    end
    
    SomeWindow.SomeFunctionPart4=function()
        if SomeDialog:GetButtonString()=="string1" then
            -- button 1 code
        elseif SomeDialog:GetButtonString()=="string2" then
            -- button 2 code
        end
        -- other code
    end
    
    SomeWindow.Update=function()
        if SomeWindow.waitFlag==1 then
            SomeWindow:SetWantsUpdates(false);
            SomeWindow.SomeFunctionPart2();
        elseif SomeWindow.waitFlag==2 then
            SomeWindow:SetWantsUpdates(false);
            SomeWindow.SomeFunctionPart3();
        elseif SomeWindow.waitFlag==3 then
            SomeWindow:SetWantsUpdates(false);
            SomeWindow.SomeFunctionPart4();
        end
    end
    
    SomeDialog.buttonString="";
    SomeDialog.GetButtonString=function()
        return SomeDialog.buttonString;
    end
    SomeDialog.Button1.MouseClick=function()
        SomeDialog.buttonString="string1";
        SomeWindow:SetWantsUpdates(true);
        SomeDialog:SetVisible(false);
    end
    SomeDialog.Button2.MouseClick=function()
        SomeDialog.buttonString="string2";
        SomeWindow:SetWantsUpdates(true);
        SomeDialog:SetVisible(false);
    end
    Note that the Update event handler is only enabled when a response button is clicked so as to prevent wasting machine cycles. You would want to be sure the window can't be closed without responding, otherwise you would have to set an appropriate default response code and only enable the Update handler when the dialog visibility changes to false but that is a fairly trivial change.

    Of course, in the simplistic case of just needing one of two response, restructuring the code would allow you to simply call the second part of the function from the button mouseclick event handlers.
    Last edited by Garan; Nov 20 2011 at 01:02 PM.

  4. #4
    Join Date
    Jun 2011
    Posts
    574

    Re: Lua: Wait command?

    Quote Originally Posted by Galuhad View Post
    I found a possible solution in coroutines, but keep getting the message, "attempt to yield across metamethod/C-call boundary". Are coroutines disabled in Lotro?
    I haven't tried using co-coroutines in lotro, but that message you might get from trying to "yield" in a section of your code that wasn't being run in a co-routine, and that would indicate to me that co-routines are enabled.

    Still, co-routines won't help you, if you do not return from your script, then the runtime cannot dispatch events, even a "busy wait loop" wouldn't work, Button.Click() would never be called. No parallel execution.

    You are going to have to handle things in an asynchronous way, as Garan suggested.

    Using Update() along with some sort of state automaton might be unnecessary complicated for what you are trying to do, a simplistic asynchronous way of doing something akin to :

    Code:
    ...
    if MessageBox() == Affirmative then
    	-- do something
    else
    	-- do something else
    end

    Might be
    Code:
    function affirmativeCase()
    	-- do something
    end
    
    function negativeCase()
    	-- do something else
    end
    
    OpenMessageBox( { <whatever list of windows you want to 'block'> }, affirmativeCase, negativeCase )
    with a rough version of a message box being:

    Code:
    local function SetWindowsEnabled( windows, enabled )
    	for _,window in pairs( windows ) do
    		window:SetEnabled( enabled );
    	end
    end
    
    local MessageBox = class(Turbine.UI.Window);
    function MessageBox:Constructor( windows, affirmativeCase, negativeCase )
    	Turbine.UI.Lotro.Window.Constructor(self);
    	
    	self.affirmativeButton = Turbine.UI.Lotro.Button();
    	self.affirmativeButton:SetParent( self );
    	...
    	self.affirmativeButton.Click = function( sender, args )
    		EnableWindows( windows );
    		self:Close();
    		affirmativeCase();
    	end
    
    	self.negativeButton = Turbine.UI.Lotro.Button();
    	self.negativeButton:SetParent( self );
    	...
    	self.negativeButton.Click = function( sender, args )
    		EnableWindows( windows );
    		self:Close();
    		negativeCase();
    	end
    
    	self:SetVisible( true );
    	DisableWindows( windows );
    end	
    
    function OpenMessageBox( windows, affirmativeCase, negativeCase )
    	messageBoxSingleton = MessageBox( windows, affirmativeCase, negativeCase );
    end
    Two tricks here being to disable your other windows so they do not receive user input, and to keep the message box in a global variable so that it does not get garbage collected right away. Come to think about it though, I've never tried disabling an entire window, I assume that works.
    Last edited by Equendil; Nov 20 2011 at 02:45 PM.
    [size=1]Freeps (Snowbourn): [b]Equanor (R11 MNS)[/b] - Equendil - Orlo - Equadoc - Quaolin - Oshia - Kaolin - Equaric - Equorn
    Creeps (Snowbourn): Veloch (R9 RVR) - Velrow (R10 BA) - Velkro - Oruk - Velrot - Velreth
    Author of the [url=http://tiny.cc/2zm50w]Legendary Item Planner[/url], [url=http://tiny.cc/m1m50w]Bootstrap[/url] and [url=http://tiny.cc/41m50w]Baruk[/url] plugins.[/size]

  5. #5
    Join Date
    Jun 2009
    Posts
    1,371

    Re: Lua: Wait command?

    Thank you both for your replies.

    I ended up making a MessageBox class instead which is working exactly as I hoped.
    If it were just one message box I wanted then it would have been easy because I would have just put the relative code into the Button.Click events.. However I wanted to use the message box for other things as well so I needed each message box to handle their own responses. I tried coroutines (with the .yield() being called within the coroutine) but kept getting errors.. I had hoped that the .yield command would pause the script while it waited for a response but no such luck. Never mind, the class is working as I want so I'm happy
    Galuhad | Narvelan
    Evernight (formally of Eldar) | Plugins
    Kinship Revamp Proposal

  6. #6
    Join Date
    Dec 2007
    Posts
    5,524

    Re: Lua: Wait command?

    When I was trying to break the backpack in the RoI Beta, I found out that plugins are, in fact, part of the same thread as the LotRO client. Or it's coded in such a way that that's effectively true.

 

 

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