What can break displaying menus?

So I have a situation where my game works fine, but if I save it and then load it then menus no longer work properly.

The options are displayed as usual, the game responds to them being clicked as usual, but the menu options don't disappear afterwards like they usually do (and throw up error messages if you keep clicking on them). Presumably you could generate some odd behaviour by doing something that showed a new menu and clicked on something from an old one.

With a bit of experimenting I've found that it only happens if you move before you save (I can start a game, save in the first room, tinker with stuff and save/load with no problems). The thing is that my move code is not simple and I've no idea what I'm looking for.

Moving calls Explore (which draws the map around the player based on a procedurally generated lookup dictionary of coordinates - the player actually stays in the same room but all of the descriptions etc. change) which in turn calls LeaveRoom (which removes all objects that are in this room because they were in the previous room) then Explore calls ExplorePart2 which calls Compass (which updates compass items the player is carrying to show the direction to certain destinations) UpdateRegion (which works out what the nearest point of interest to the player is and stores it for various purposes) and CheckWalls (which determines which exist to make invisible to properly simulate the player being in the point on the map specified) When all that's done it calls RandomEncounter but I tried turning that off and it didn't fix anything so I'm confident it's not that.

Basically there's a lot of stuff going on when the player moves and I've no notion of why any part of it should mean that ShowMenu works fine - but will now break if the player saves and then loads.

What sort of mistake am I even looking for?


Okay so after a bunch of commenting out code etc. I've managed to isolate the bug and it looks like a problem with Quest

If you use ClearScreen() then the save appears permanently broken such that if the user saves and then loads then ShowMenu() will cause menu options to fail to disappear when clicked on.

Replicated in a program that was just the default setup with an extra object that had two verbs, one for clearing the screen and one for showing a menu.

Anyone else had this problem? Kinda an issue if ClearScreen() permanently breaks my saves.


K.V.

I use ClearScreen quite frequently in the three games I've got going on, and I haven't had any problems loading the save games.

I even call the ClearScreen function inside of my modified Save command so it clears the screen before saving. (This is just to keep the player from having to wait for the game to scroll through everything when loading the saved game.)


Do you have a copy of the test game you made?

I'll play around with it, if you post it.


Does your game use ShowMenu? The specific problem is that the behaviour of that function changes after saving a game that's invoked ClearScreen

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Test">
    <gameid>eb0d1436-8c1f-4a0e-b0e9-3a0585ff5d25</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="thing">
      <inherit name="editor_object" />
      <clearscreen type="script">
        ClearScreen
      </clearscreen>
      <showmenu type="script">
        ShowMenu ("Menu", Split("One;Two",";"), true) {
        }
      </showmenu>
    </object>
  </object>
  <verb>
    <property>clearscreen</property>
    <pattern>clearscreen</pattern>
    <defaultexpression>"You can't clearscreen " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>showmenu</property>
    <pattern>showmenu</pattern>
    <defaultexpression>"You can't showmenu " + object.article + "."</defaultexpression>
  </verb>
</asl>

That's the minimum program I've been able to replicate it with. If you save and load it works fine. If you use the clearscreen verb on the object it works fine. If you use the clearscreen verb and then save and load the show menu verb starts misbehaving.


K.V.

Hmm....

I added a message that prints the result you chose, and it appears ShowMenu just isn't clearing the menu after you choose something.

> showmenu thing
Menu
1: One
2: Two
You chose One

> showmenu thing
Menu
1: One
2: Two
You chose Two


Before I added that, I thought it wasn't doing anything when you selected something.

It always prints this when you click on a selection after you've already selected something from the menu the first time: Error running script: Unexpected menu response.


But, yes.

After you clear the screen, save the game, then load, the ClearMenu function appears to be broken.


K.V.

...but...

I have a game with a ClearScreen command and MANY ShowMenu inducing verbs.

I just tested it on that, and it works fine.

So, maybe it's because it's a verb?

That makes no sense, I know, but I'm about to test the theory out.


K.V.

You can start the game. Clear the screen. Load the saved game.

Then, the menu is messed up.


Here's the function that's supposed to clear the menu on click (from the saved game):

<function name="ShowMenuResponse" parameters="option">
    if (game.menucallback = null) {
      error ("Unexpected menu response")
    }
    else {
      parameters = NewStringDictionary()
      dictionary add (parameters, "result", UnescapeQuotes(option))
      script = game.menucallback
      ClearMenu
      invoke (script, parameters)
    }
  </function>

Here's the one that's supposed to do it if you enter a command to select:

<function name="HandleMenuTextResponse" parameters="input" type="boolean"><![CDATA[
    handled = false
    if (IsInt(input)) {
      number = ToInt(input)
      if (number > 0 and number <= ListCount(game.menuoptionskeys)) {
        handled = true
        ShowMenuResponse (StringListItem(game.menuoptionskeys, number - 1))
      }
    }
    return (handled)
  ]]></function>

And ClearMenu:

<function name="ClearMenu">
    HideOutputSection (game.menuoutputsection)
    game.menuoutputsection = null
    game.menuoptions = null
    game.menucallback = null
  </function>

Now, the debugger shows game.menuoutputsection when you haven't selected a menu option yet, and it definitely goes back to null once you make a selection. The menu just doesn't clear.

It's strange that it works in my other game, though.

I'm about to make a game from scratch and test it.

...and it still messes up in a new game.

...but it all works perfectly fine in the game I've been working on for a month or two. Like I say, it has a clear command, and very many things that call ShowMenu. I just tested it every which way but loose, and there was no problem with the menus after clearing the screen and saving.

What a mystery...


I'm thinking the issue is in the JS function that's supposed to hide the section, but I don't know jQuery well enough to poke further.


K.V.

The JS function:

I wanted to think that, but the JS functions shouldn't change at all on save, should they?


All of those scripts I posted are directly from the saved game, too.

It was bed time. I'm about to run a DIFF on the scripts now, but I doubt anything is different.

If it is in the JS function: If I can't bulldog through to figure it out, I bet Pixie can point it out quickly.


The most confusing thing is that my game I've been building for months has a Clear Screen command and ShowMenus everywhere you click, but it doesn't have the problem.

The game I created last night does, though...


Hmm. Have you done anything unusual with the interface in your game?

I'm curious about why it works fine the existing game, but we can easily replicate the problem elsewhere.

It already seemed a bit of a head-scratcher, now I've no idea what to do!


K.V.

>Have you done anything unusual with the interface in your game?

I started on it before I updated to 5.7...

That's the only thing I've come up with that may matter...

...but I don't see how it could...

...but I can't say that it couldn't.


>It already seemed a bit of a head-scratcher, now I've no idea what to do!

That's what I'm screaming!


Are you online or using the desktop editor?


I'm about to publish my example game and see if it happens in the online player.


I don't know how that happens; as I can't find the message that's sent to the client on restoring a save. But I can see how that kind of error could occur based on the bits of code I've seen.

If I'm right, the error would be linked to an empty section (<div />) in the restored output; so clearing the screen immediately before saving.


K.V.

mrangel,

Oh, I think I'm following you.

Clearing the screen deletes the div element that ClearMenu is trying to delete?


K.V.

In an unsaved game, the div element just keeps increasing n at the end of divOutputAlign:

<div id="divOutputAlign26"

image


...but it's adding NaN in the loaded save game:

<div id="divOutputAlignNaN"

image


K.V.

Might it be something in this (specifically, the createNewDiv function):

function addText(text) {
    if (getCurrentDiv() == null) {
        createNewDiv("left");
    }

    getCurrentDiv().append(text);
    $("#divOutput").css("min-height", $("#divOutput").height());
}

function createNewDiv(alignment) {
    var classes = _outputSections.join(" ");
    setDivCount(getDivCount() + 1);
    $("<div/>", {
        id: "divOutputAlign" + getDivCount(),
        style: "text-align: " + alignment,
        "class": classes
    }).appendTo("#divOutput");
    setCurrentDiv("#divOutputAlign" + getDivCount());
}

var _currentDiv = null;

function getCurrentDiv() {
    if (_currentDiv) return _currentDiv;

    var divId = $("#outputData").attr("data-currentdiv");
    if (divId) {
        _currentDiv = $(divId);
        return _currentDiv;
    }

    return null;
}

function setCurrentDiv(div) {
    _currentDiv = $(div);
    $("#outputData").attr("data-currentdiv", div);
}

var _divCount = -1;

function getDivCount() {
    if (_divCount == -1) {
        _divCount = parseInt($("#outputData").attr("data-divcount"));
    }
    return _divCount;
}

function setDivCount(count) {
    _divCount = count;
    $("#outputData").attr("data-divcount", _divCount);
}

K.V.

Oh yeah...

Here's this, too:

function clearScreen() {
    $("#divOutput").css("min-height", 0);
    $("#divOutput").html("");
    createNewDiv("left");
    beginningOfCurrentTurnScrollPosition = 0;
    setTimeout(function () {
        $("html,body").scrollTop(0);
    }, 100);
}

K.V.

It does it online, too.


http://textadventures.co.uk/games/view/5vghpddwzks0vbqg3zkt5g/clear-screen-showmenu-test

  1. Clear your screen
  2. SAVE
  3. [QUIT THE GAME]
  4. Load the saved game
  5. Click or enter: Choices to make

At this point, you can make a selection, but the menu does not clear. Then, if you click on something, it throws an error (of course).


Is the player that launches a saved game accessing a different playercore.js?

Was there a file name or location change in the update to 5.7 that didn't make it into the player that launches a saved game? (I only theorize that it may be a different player because the window is set up totally differently. I may be being completely silly.)

All the text I used <s> on has to be wrong, because the online player does the same thing.


K.V.

Falsy values in JavaScript are false, null, 0, "", undefined, and NaN.

-from freecodecamp.org


K.V.

I think the divCount is NaN (which I'm guessing means Not a Number).


K.V.

I just updated the example game.

You can now use JS functions to debug/fix/whatever.

JS.clearScreen() will clear the screen.

JS.addText("Hello Forum") will print Hello Forum.

JS.setDivCount(42) does this (it assigns a number to divOutputAlign, which fixes ClearMenu):

image


> save

> menu
Pick one
1: one
2: two
one

> JS.setDivCount(42)

> menu
one


K.V.

Put this in your user interface initialization script. It will fix the menu problem:

JS.getDivCount ()


K.V.

Fixed.

You just add that one line (JS.getDivCount()) to your user interface initialisation script.

Example game:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="clrtest">
    <gameid>6b741173-fc50-4668-a656-eda0d6db9b45</gameid>
    <version>1.1</version>
    <firstpublished>2017</firstpublished>
    <feature_advancedscripts />
    <commandpane />
    <inituserinterface type="script">
      JS.setCommands ("clear;menu;save;look", "black")
      JS.getDivCount () //This is the fix
    </inituserinterface>
    <description><![CDATA[Just an example game.<br/><br/>ShowMenu breaks if you save the game after clearing the screen, but I found a fix.]]></description>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <enter type="script">
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <command>
    <pattern>clear</pattern>
    <script>
      ClearScreen
    </script>
  </command>
  <command>
    <pattern>menu</pattern>
    <script>
      ShowMenu ("Pick one", Split ("one;two", ";"), true) {
        msg (result)
      }
    </script>
  </command>
</asl>

It's around time for The Pixie to be checking in on us...

Maybe I can find the wiki page where he explains how Quest loads things when loading a saved game before he sees this one...


https://github.com/ThePix/quest/wiki/UI-Part-05:-Where-and-When-To-Do-Stuff


K.V.

Hrmm...

Does Quest not have like a default initialisation script?

If I could find that (if it exists), I could just add the line in my Quest 5 folder and just roll with it.


Help!

I tried to find it, Pixie!

I really, really tried!


Thanks K.V. that works perfectly :)

I'm still trying to follow how you worked it out! It looks like you're seeing parts of the engine I'm not - the code for (for example) ShowMenu isn't in my game so I had no chance to spot the thing (Not that I imagine I'd have been particularly likely to, I think you're cleverer than me, but it'd have been nice to give it a go). Presumably when I include the lines

<include ref="English.aslx" />
<include ref="Core.aslx" />

I'm pulling in a bunch of other functions from somewhere, but I don't know where from or how to look at them. Presumably I don't open them in quest so much as grab another program to look at them?

I don't imagine this'll come up again, but it's nice to see how things work :) Thanks again!


K.V.

I'm pulling in a bunch of other functions from somewhere, but I don't know where from or how to look at them.

Yep, you've pretty much got it!

If you want to see those functions, click on Filter, then Show Library Elements at the bottom left of the desktop editor:

image


http://docs.textadventures.co.uk/quest/overriding.html

http://docs.textadventures.co.uk/quest/functions/hardcoded.html


...but that wasn't what I did here, because I was looking for something that might have changed in the save file.

So I navigated to the directory where the save file was located, right-clicked it, opened it up with Notepad++, and voila, all of the functions (even the ones you can't see by default in the editor)!


K.V.

My fix worked as far as ShowMenu was concerned, but it messed up the way Quest prints text to the screen!

See this post:

http://textadventures.co.uk/forum/quest/topic/ik0dbblaq0o5fdqq7nuwia/js-function-to-find-the-last-divoutputalign-in-a-saved-game


Actually, you can skip to the solution. The fix here is not good.

Sorry!


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums