HTML [Solved ] [Sugarcube] using widget to pass $args[0] into a javascript

Frogface29

Newbie
Feb 22, 2022
43
41
Hi,

I am currently creating a script that has the following code for an exitButton inside a widget.
Code:
    exitButton.addEventListener('click', () => {
      console.log('Exiting the game');
      saveState();

      // Check if a passage name was provided as an argument
      const passageName = $args[0] || State.variables.previousPassage;

      if (passageName) {
        // Navigate to the specified passage or the previous passage
        Engine.play('passageName');
      }
    });
The idea here is that I can call <<widget "passage1">> and then go to passage1 when the exit button is pressed. If I just say <<widget>> it should return to the previous passage. That does not work, however.
The whole thing (and lots of other code) is wrapped in <<done>> and <<script>>.

My question is: Can I even use $args[0] to affect javascript code? And is the method of calling the previousPassage correct or should I use previous()?

Thanks!
 
Last edited:

Satori6

Game Developer
Aug 29, 2023
367
674
Hi,

I am currently creating a script that has the following code for an exitButton inside a widget.
Code:
    exitButton.addEventListener('click', () => {
      console.log('Exiting the game');
      saveState();

      // Check if a passage name was provided as an argument
      const passageName = $args[0] || State.variables.previousPassage;

      if (passageName) {
        // Navigate to the specified passage or the previous passage
        Engine.play('passageName');
      }
    });
The idea here is that I can call <<widget "passage1">> and then go to passage1 when the exit button is pressed. If I just say <<widget>> it should return to the previous passage. That does not work, however.
The whole thing (and lots of other code) is wrapped in <<done>> and <<script>>.

My question is: Can I even use $args[0] to affect javascript code? And is the method of calling the previousPassage correct or should I use previous()?

Thanks!

According to the , the correct usage would be _args[0]

SugarCube said:
Deprecated the $args variable in favor of _args.
 

guest1492

Member
Apr 28, 2018
312
262
And is the method of calling the previousPassage correct or should I use previous()?
You should use previous(). State.variables.previousPassage would not mean anything unless you specifically assign something to it. SugarCube itself certainly doesn't create or update such a variable.

As mentioned, $args is deprecated in favor of _args. You can still use it, but you shouldn't. Code that is wrapped in the <<script>><</script>> macro does not get "de-sugared" so $args (or _args) would not mean anything. You would need to use State.variables.args (for $args) or State.temporary.args (for _args). Note that code passed to the <<run>> or <<set>> macro does get de-sugared, but it seems kind of awkward to write a whole block of code in one.

However, that still might not fix the problem because you are adding an event listener, so that's executed asynchronously (when the button is clicked). By that time, _args might no longer be what it was when the event listener was assigned (which is presumably when the passage is first rendered). Actually, I'm sure that it is no longer the same.

The code should be changed to this:

JavaScript:
// Check if a passage name was provided as an argument
const passageName = State.temporary.args[0] || previous();

exitButton.addEventListener('click', () => {
    console.log('Exiting the game');
    saveState();

    if (passageName) {
        // Navigate to the specified passage or the previous passage
        Engine.play(passageName);
    }
});
That should work as long as you have exitButton and saveState() defined somewhere in an accessible scope.

EDIT: removed quotes inside Engine.play().
 
Last edited:
  • Like
Reactions: Frogface29

Alcahest

Engaged Member
Donor
Game Developer
Jul 28, 2017
3,139
4,034
Unless you have a specific reason to use a listener, you can use <<button>>. This works when I test it.
Code:
<<widget exit>>
    <<set $passageName = _args[0] || previous()>>
    <<button "Exit">>
        <<script>>
            console.log('Exiting the game');
            saveState();
            if (State.variables.passageName) {
                /* Navigate to the specified passage or the previous passage */
                Engine.play(State.variables.passageName);
            }
        <</script>>
    <</button>>
<</widget>>
Note the absence of ' in Engine.play(). Doing Engine.play('passageName') will try to send you to a passage literally named passageName
 
Last edited:

Frogface29

Newbie
Feb 22, 2022
43
41
You should use previous(). State.variables.previousPassage would not mean anything unless you specifically assign something to it. SugarCube itself certainly doesn't create or update such a variable.

As mentioned, $args is deprecated in favor of _args. You can still use it, but you shouldn't. Code that is wrapped in the <<script>><</script>> macro does not get "de-sugared" so $args (or _args) would not mean anything. You would need to use State.variables.args (for $args) or State.temporary.args (for _args). Note that code passed to the <<run>> or <<set>> macro does get de-sugared, but it seems kind of awkward to write a whole block of code in one.

However, that still might not fix the problem because you are adding an event listener, so that's executed asynchronously (when the button is clicked). By that time, _args might no longer be what it was when the event listener was assigned (which is presumably when the passage is first rendered). Actually, I'm sure that it is no longer the same.

The code should be changed to this:

JavaScript:
// Check if a passage name was provided as an argument
const passageName = State.temporary.args[0] || previous();

exitButton.addEventListener('click', () => {
    console.log('Exiting the game');
    saveState();

    if (passageName) {
        // Navigate to the specified passage or the previous passage
        Engine.play(passageName);
    }
});
That should work as long as you have exitButton and saveState() defined somewhere in an accessible scope.

EDIT: removed quotes inside Engine.play().
Thanks, that worked!
 

Frogface29

Newbie
Feb 22, 2022
43
41
Unless you have a specific reason to use a listener, you can use <<button>>. This works when I test it.
Code:
<<widget exit>>
    <<set $passageName = _args[0] || previous()>>
    <<button "Exit">>
        <<script>>
            console.log('Exiting the game');
            saveState();
            if (State.variables.passageName) {
                /* Navigate to the specified passage or the previous passage */
                Engine.play(State.variables.passageName);
            }
        <</script>>
    <</button>>
<</widget>>
Note the absence of ' in Engine.play(). Doing Engine.play('passageName') will try to send you to a passage literally named passageName
Thanks!