Unexpected error messages with nested Wait { }

A game I'm working on has nested wait operations to release text in chunks. When I respond to a 'continue' with the space bar I sometimes get an error message:

Error running script: Only one wait can be in progress at a time.

Anyone know why this happens and what I can do about it?


It means that Quest is still waiting for the first continue to be clicked when the second starts, which would suggest your wait blocks are not properly nested. Just guessing, but do you have more than two? I would see if the thord is properly nested in the second.


As this is a transient error I'm assuming it is something to do with the way that Quest is preprocessing the code for execution and executing it in parallel with user input. I've simplified the structure and removed one of the waits, which seems to have made the problem go away!


This is not properly nested, and will throw the error of which you speak:

msg ("hello")
wait {
  msg ("Hello")
}
wait {
  msg ("HELLO!")
}

image


This is properly nested:

msg ("hello")
wait {
  msg ("Hello")
  wait {
    msg ("HELLO!")
  }
}


other possibilities (though bad syntax/nesting is the most likely cause, unless you're trying to do looping - see below):

  1. you're looping, which just can't be done with waited-on-inputs from the player, be it 'wait', 'get input', 'show menu', or whatever else, unfortunately in quest)

  2. you're having scripts (which use the 'wait') running at the same time, such as maybe through using the special 'change' scripts.


Is this sort of code a problem as well? ...why does 'faulty code' not fail every time?

if (test) {
    wait {...}
 }
 else {
    wait {...}
 }

That should be fine.

The only reason for it only happening sometimes is that some of the code is only firing sometimes. This will fail if test is true, but will be fine if it is false:

if (test) {
  wait {...}
}
wait {...}
 

I keep hoping someone will say "Hey, I've had that problem, here's what you do..." I'm going to have to investigate to explain more about this issue. It does feel as if something is happening lower down over which I have no control and no knowledge. Back soon...


Here is an example game that has your problem. If you look at the room, it will be okay, unless you are holding the teapot, in which case you will get your error message. The problem is in the "description" script of the room.

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="wait_error">
    <gameid>0f0486a9-e5b2-4f8a-abc3-1519b40c8737</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <description type="script">
      msg ("You look around the room...")
      if (Got(teapot)) {
        wait {
          msg ("Even as you feel the weight of the teapot in your arms...")
        }
      }
      wait {
        msg ("... It's just a room.")
      }
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="teapot">
      <inherit name="editor_object" />
      <take />
    </object>
  </object>
</asl>

Here is test code that shows the problem...at least on my machine!

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Nested Waits">
    <gameid>3b83f264-2b03-4ce5-8dac-95788bb3dfb7</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="wait responder">
      <inherit name="editor_object" />
      <dowait type="script"><![CDATA[
        msg ("Start here...")
        wait {
          msg ("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.<br/>")
          wait {
            msg ("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.<br/>")
            wait {
              msg ("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.<br/>")
              wait {
                msg ("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.<br/>")
                wait {
                  msg ("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.<br/>")
                }
              }
            }
          }
        }
      ]]></dowait>
      <look>Code to illustrate nested wait problem.</look>
    </object>
  </object>
  <verb>
    <property>dowait</property>
    <pattern>dowait</pattern>
    <defaultexpression>"You can't dowait " + object.article + "."</defaultexpression>
  </verb>
</asl>

Does it work if you changed the contents of the big messages?
If it only happens if you're displaying huge messages, maybe it could be some kind of timing issue or race condition?


I found it happening when there were several levels of nesting and quite a bit of text to display. I thought it might be due to hitting the space bar while text was being displayed but I found this code brought up the problem immediately though not every time! ...so it looks like a race condition issue.


DavyB,

Your example game throws no errors on my machine.

I'm running Quest 5.7.2 on Windows 10.


I keep hoping someone will say "Hey, I've had that problem, here's what you do..."

Hey, I've had that problem!

Here's what I do: http://textadventures.co.uk/forum/quest/topic/fi7rs8pxxkmfgb6z2xk5eg/unexpected-error-messages-with-nested-wait#51ca5b7f-a217-4836-b762-1991d57289b0

...but that is what you did in your example game, and your example works on my machine...

Have you tested your example game to make sure it throws errors? Or did you just assume it would? (I only ask because I make such assumptions quite frequently, only to find that I failed to recreate the error.)


Hi KV, that game fails on my machine quite consistently. I'm running Windows 8. It fails in different ways in different places. I made Quest hang up completely at one point and needed to use the Task Manager to stop it! I can try it on Windows 7...


...yes, I can get it to fail under Windows 7 as well. Have you tried hitting the space bar while text is being displayed? i.e. not waiting for the continue to appear?


Have you tried hitting the space bar while text is being displayed?

I just spammed the spacebar all the way through it. No errors here.

I'm going to try on my Windows 7 machine.


No errors using Windows 7 on my end, either.


Hi KV, that game fails on my machine quite consistently. I'm running Windows 8.

This is referencing the example game that you just posted, correct?

It fails in different ways in different places.

Which different ways in which different places?

I can only find one way to trigger the script. From there, I can either click the link (which is error-free on my end) or press any key (which is error-free on my end).


I'm not implying that you have an imaginary problem or anything. I just can't recreate the error, and I wanted to see it so I could help.


KV, I've sent a screen shot to you by gmail. Couldn't seem to paste it here?


Got the screenshot.

It looks like that is being clicked more than once in the pane. Each click starts the script from the beginning instead of ending the wait.


In playercore.js, in the initial function, in the bit of code starting on line 97:

I changed the onclick script for the elementmenu class to avoid the error when clicking on something in the pane during a wait:

    $(document).on("click", ".elementmenu", function (event) {
            // KV added this check for wait mode
            if(_waitMode){
                endWait();
                return;
	    }
            // END OF ADDITION BY KV
	    if (!$(this).hasClass("disabled")) {
            event.preventDefault();
            event.stopPropagation();
            $(this).jjmenu_popup();
            $(this).blur();
            return false;
        }
    });

I also just noticed that pressing ENTER while a button in the pane is selected has a different effect than clicking it!

This will cause the error, too!!!

Be right back!


Okay...

When clicking on a button in the pane, the button remains selected. Then, pressing enter "clicks" that button, but it doesn't seem to be handled as an actual click. Something to do with submitting forms I think...


Just to summarise my understanding so far. If a player waits for continue to appear and clicks on it, all is fine. Hitting any key should also work and I'd become used to hitting the space bar instead of clicking. Failures can sometimes occur in that situation if the space bar is pushed before the next continue appears. Experimenting, I find that hitting most keys is also fine but return is a problem as well as the space bar. I guess this hasn't come up before because most players patiently wait to click 'continue'!


Alrighty...

image


When clicking on "dowait" in the pane under 'wait responder', the button stays selected. Pressing a key afterwards caused that to somehow simulate a button click which onclick couldn't prevent. So, I added code to take the focus off of a ui-button on clicking it.

$('.ui-button').on("click",function(e){$(this).blur();if (_waitMode){endWait();e.preventDefault;e.stopPropagation;}});

That works as long as the player doesn't use tab to select the button.

This keeps the player from selecting a button during a wait:

$('.ui-button').on("focus",function(e){if (_waitMode){$(this).blur();}});

So, I put it all together, and add this line to game.inituserinterface:

JS.eval ("$(document).on(\"click\", \".elementmenu\", function (event) {if(_waitMode){endWait();return;}if (!$(this).hasClass(\"disabled\")) {event.preventDefault();event.stopPropagation();$(this).jjmenu_popup();$(this).blur();return false;}});$('.ui-button').on(\"click\",function(e){$(this).blur();if (_waitMode){endWait();e.preventDefault;e.stopPropagation;}});$('.ui-button').on(\"focus\",function(e){if (_waitMode){$(this).blur();}});")

Thanks KV, all now seems perfect. Will that code be in the next release?


It works!

Awesome!


That's definitely a bug. I think something that has the same effect will probably be added. (Pixie will probably know a better (or more efficient) way to handle it.)


Okay, for the moment I can slot that code into games as a workaround. Thanks for your help.


That looks like quite an ugly workaround to me :S You're using script to move the focus off the buttons, rather than actually disabling the buttons. I think the error might still occur if a Timeout event (in Quest or in Javascript) starts a 'wait' while the player is clicking the verb button, before they release the mouse.

Wouldn't changing the verb buttons so they can't be clicked be more efficient? Or have I missed something? My first instinct would be to try changing the function that handles the click.

function paneButtonClick(target, button) {
    if (_waitMode) return;

(followed by the rest of that function as it is)


That sounds more efficient, but it still doesn't keep the ENTER button from sending a click through while the button is selected.


OK, I don't understand that.

Does pressing enter on a verb button not call paneButtonClick?

EDIT: No, I don't get this at all.
Clicking the verb buttons calls paneButtonClick; which extracts the selected object name and the verb name, composes them into a command, and calls sendCommand().

Which should then return without doing anything if _waitMode is true.
All the functions which actually pass data back to the server check _waitMode first, ensuring that no clicks get back to the server while waiting.
(... actually, only true in the web version. I assume the desktop version performs this check somewhere else?)


Seems to be doing the same in desktop version. It's confused me as well.

I tried onkeypress on everything, but to no avail. That's why I broke down and used onfocus to blur the damned button.


Aha! You led me to the problem, mrangel!

sendCommand() doesn't check for _waitMode in desktopplayer.js!

This seems to do the trick:

JS.eval ("function sendCommand(text, metadata) { if(_waitMode){endWait();return;}   markScrollPosition();    var data = new Object();    data[\"command\"] = text;    if (typeof metadata != \"undefined\") {        data[\"metadata\"] = metadata;    }    UIEvent(\"RunCommand\", JSON.stringify(data));}")

The same thing in actual Javascript:

function sendCommand(text, metadata) { 
    // Added by KV
    if(_waitMode){
        endWait();
        return;
    }
    // END OF ADDITION BY KV
    markScrollPosition();
    var data = new Object();
    data["command"] = text;
    if (typeof metadata != "undefined") {
        data["metadata"] = metadata;
    }
    UIEvent("RunCommand", JSON.stringify(data));
}

...I've taken away [SOLVED] while the discussion continues... :)


If it were up to me (and no one pointed out any flaws), I would have this:

$(window).on('keydown',function(e){
    if(_waitMode){
    	endWait();
    	e.preventDefault();
    	e.stopPropagation();
    }
});

$(window).on('click',function(e){
    if(_waitMode){
    	endWait();
    	e.preventDefault();
    	e.stopPropagation();
    }
});

Any button press or any click anywhere in the window will runendWait() with this setup. I've tested it out, and I can't see that it breaks anything. Plus, you can hit Enter or the spacebar while that button is in focus, and it doesn't throw the error.


That looks AND feels good. I've also tried it out and don't see any issues. You must be close to an optimal solution KV!


I'm not sure that catching all clicks is a good thing.
Would that mean that if you click the label of the inventory pane, for example, it would end the wait instead of expanding/collapsing the pane? Will clicking the scroll bar (as if anyone still uses that) end a wait?

I can imagine situations where the game gives you a "Continue ..." button before starting a timed puzzle; in which case players might still want to show the compass and inventory, and even select the relevant item in the inventory to save a second or two. I'd expect that to be supported; only triggering the 'continue' when you actually try to do something.

Different players might have different expectations, but I would expect that a "Continue..." link would block me from taking any game actions. I wouldn't expect it to be dismissed by clicking on display elements that don't correspond to any activity by the player character.

(haven't tested it yet, but I'm also curious how this would interact with my drag-and-dock panes script)


The clicks and keypresses already either end the wait, cause errors, or simply don't work when _waitMode is true.

Is _waitMode ever true without an author initiating it to pause play?


Would that mean that if you click the label of the inventory pane, for example, it would end the wait instead of expanding/collapsing the pane?

Good point!


Will clicking the scroll bar (as if anyone still uses that) end a wait?

It didn't, but I had to test it to make sure!

I can imagine situations where the game gives you a "Continue ..." button before starting a timed puzzle; in which case players might still want to show the compass and inventory, and even select the relevant item in the inventory to save a second or two. I'd expect that to be supported; only triggering the 'continue' when you actually try to do something.

Very good thinking!

$(window).on('keydown',function(e){
    if(_waitMode){
    	endWait();
    	e.preventDefault();
    	e.stopPropagation();
    }
});

$('#divOutuput').on('click',function(e){
    if(_waitMode){
    	endWait();
    	e.preventDefault();
    	e.stopPropagation();
    }
});

Did this fix end up in 5.8? I don't see it mentioned. Happy to continue with the patch but obviously better if I can leave it out.


I don't think it was added (not 100% sure, though).


For online authors (or desktop authors) who want to experiment with this, you can add this to your User Interface Initialisation script:

// Apply WAIT fix
JS.eval("$(window).on('keydown',function(e){     if(_waitMode){     	endWait();     	e.preventDefault();     	e.stopPropagation();     } });  $('#divOutuput').on('click',function(e){     if(_waitMode){     	endWait();     	e.preventDefault();     	e.stopPropagation();     } });")

Log in to post a reply.

Support

Forums