Sugarcube 2.36.1 questions

Studio31

New Member
Oct 30, 2018
14
19
Hey there,

I am fairly new to Sugarcube and twine but have "attempted" making 1 or 2 games in the past and as such have picked up a few things. I am currently stumped by this however and cannot get a rent system to work. So, first question :
How do I implement a way that each Sunday at 'Pre bed' passage the player gets paid X amount. In this example I want it to increase depending on the number of tenants in the players building. Currently I tried this way as I got it to work the first Sunday but not the following weeks:

Code:
<<if $day == 7>>
        <<if $tenant == 1>>
                <<set $day == 0>>
             <<set $money += 100>>
 <<speech "You" "$name">>
Rent should be in the account today!
<</speech>>
        <<elseif $tenant == 2>>
                <<set $day == 0>>
             <<set $money += 200>>
              <<speech "You" "$name">>
Rent should be in the account today!
<</speech>>
         <<elseif $tenant == 3>>
                <<set $day == 0>>
             <<set $money += 300>> 
              <<speech "You" "$name">>
Rent should be in the account today!
<</speech>>
         <<elseif $tenant == 4>>
                <<set $day == 0>>
             <<set $money += 400>>
              <<speech "You" "$name">>
Rent should be in the account today!
<</speech>>
        <<elseif $tenant == 0>>
                <<set $day == 0>>   
              <<speech "You" "$name">>
Rent should be in the account today!
<</speech>>
        <</if>>
<</if>>
And the sleep system I have is this:
Code:
<<if $period == 6 and passage() != "Pre Bed">><<goto [[Pre Bed]]>><</if>>
The second question I have is minor in terms of importance to the game but more of a nice to have, Is there a way to set my images to expand when clicked, pop up box that shows them bigger.

Any help is much appreciated and if you need any more info or I have left something out, let me know!
 

Alcahest

Engaged Member
Donor
Game Developer
Jul 28, 2017
3,484
4,330
You use == instead of = when setting the day. That might be all that's wrong.

You also repeat the same code for no reason. The entire thing could be written like this:
Code:
<<if $day == 7>>
    <<set $day = 0>>
    <<set $money += $tenant * 100>>
     <<speech "You" "$name">>
        Rent should be in the account today!
    <</speech>>
<</if>>
So instead of having to change what's wrong several times, you just need to change it once. Don't repeat code unless for a good reason.
 
  • Like
Reactions: Satori6

guest1492

Member
Apr 28, 2018
350
288
For redirecting to your "Pre Bed" passage, it's better to use . Stick this in your JS instead:

JavaScript:
Config.navigation.override = function (dest) {
    if (State.variables.period >= 6)
        return "Pre Bed";
    return false;
};
As for expanding images or having a pop up window with them, it depends on exactly how you want it to work. My idea would involve a little JS and CSS. (I spent way too much time on this.)

JavaScript:
(function () {
    const $popup = $(document.createElement('div'))
        .attr('id', 'imgPopUp')
        .on('click', () => $popup.removeClass('open'))
        .appendTo(document.body);

    $(document).on('click', 'img', (ev) => {
        /* make sure that the image is still on the page to account for image links */
        if (!document.body.contains(ev.target)) return;
        /* hopefully this will catch broken images */
        if (ev.target.naturalHeight == 0 || ev.target.naturalWidth == 0) return;

        $popup
            .css('background-image', `url('${ev.target.src}')`)
            .addClass('open');
    });

    $(document.head).append(`<style>
        #imgPopUp {
            display: none;
            position: fixed;
            inset: 0;
            z-index: 100200;
            background-color: rgba(0, 0, 0, 0.75);
            background-size: contain;
            background-position: center;
            background-repeat: no-repeat;
        }
        #imgPopUp.open {
            display: block;
        }
    </style>`);
}());
 
Last edited:
  • Like
Reactions: Alcahest

Studio31

New Member
Oct 30, 2018
14
19
Wow thanks for that guys! Really appreciate you taking the time to respond! Alcahest Thanks for the code, I didn't even know you could do that so thank you, I have tested it and it works!

guest1492 Thanks so much for spending time and effort on this! I added the Java and It gives me an error when opening chrome and it causes issues with my JS for <<speech>> so I wasn't able to test. But don't worry about spending more time on it! I appreciate you helping!

Screenshot 2024-01-18 200312.png
 
  • Yay, update!
Reactions: Alcahest

Studio31

New Member
Oct 30, 2018
14
19
Oops, I left out a semicolon after the last } in the navigation override.
Hey so new error but if you ignore it it works! Your a god damn saint haha Now it might be something I have done so I have attached the error and I pasted the entire code you gave into the JS (Firstly I though they had to be separate JS and CSS but that just gave the error and didn't work) So Here is the error and my JS file with your code at the bottom in case something is clashing. My JS knowledge is 0 and the JS that's in there is all copied from other sources so...
Screenshot 2024-01-19 093026.png

JavaScript:
/* speech macro - Start */
Macro.add('speech', {
    tags     : null,
    handler  : function () {
        var id = this.args[0], name = id;
        if (this.args.length > 1) name = this.args[1];
        var output = '<div class="speech ' + id + '">';
        output += '<span class="avatar"></span>';
        output += name + '<hr>' + this.payload[0].contents + '</div>';
        $(this.output).wiki(output);
    }
});
/* speech macro - End */

/* thought macro - Start */
Macro.add('thought', {
    tags     : null,
    handler  : function () {
        var id = this.args[0], name = id;
        if (this.args.length > 1) name = this.args[1];
        var output = '<div class="speech ' + id + '">';
        output += '<span class="avatar"></span>';
        output += name + '<hr>' + this.payload[0].contents + '</div>';
        $(this.output).wiki(output);
    }
});
/* thought macro - End */

/* For pre bed*/
Config.navigation.override = function (dest) {
    if (State.variables.period >= 6)
        return "Pre Bed";
    return false;
}

(function () {
    const $popup = $(document.createElement('div'))
        .attr('id', 'imgPopUp')
        .on('click', () => $popup.removeClass('open'))
        .appendTo(document.body);

    $(document).on('click', 'img', (ev) => {
        /* make sure that the image is still on the page to account for image links */
        if (!document.body.contains(ev.target)) return;
        /* hopefully this will catch broken images */
        if (ev.target.naturalHeight == 0 || ev.target.naturalWidth == 0) return;

        $popup
            .css('background-image', `url('${ev.target.src}')`)
            .addClass('open');
    });

    $(document.head).append(`<style>
        #imgPopUp {
            display: none;
            position: fixed;
            inset: 0;
            z-index: 100200;
            background-color: rgba(0, 0, 0, 0.75);
            background-size: contain;
            background-position: center;
            background-repeat: no-repeat;
        }
        #imgPopUp.open {
            display: block;
        }
    </style>`);
}());
 

Alcahest

Engaged Member
Donor
Game Developer
Jul 28, 2017
3,484
4,330
Hey so new error but if you ignore it it works! Your a god damn saint haha Now it might be something I have done so I have attached the error and I pasted the entire code you gave into the JS (Firstly I though they had to be separate JS and CSS but that just gave the error and didn't work) So Here is the error and my JS file with your code at the bottom in case something is clashing. My JS knowledge is 0 and the JS that's in there is all copied from other sources so...
View attachment 3276490

JavaScript:
/* speech macro - Start */
Macro.add('speech', {
    tags     : null,
    handler  : function () {
        var id = this.args[0], name = id;
        if (this.args.length > 1) name = this.args[1];
        var output = '<div class="speech ' + id + '">';
        output += '<span class="avatar"></span>';
        output += name + '<hr>' + this.payload[0].contents + '</div>';
        $(this.output).wiki(output);
    }
});
/* speech macro - End */

/* thought macro - Start */
Macro.add('thought', {
    tags     : null,
    handler  : function () {
        var id = this.args[0], name = id;
        if (this.args.length > 1) name = this.args[1];
        var output = '<div class="speech ' + id + '">';
        output += '<span class="avatar"></span>';
        output += name + '<hr>' + this.payload[0].contents + '</div>';
        $(this.output).wiki(output);
    }
});
/* thought macro - End */

/* For pre bed*/
Config.navigation.override = function (dest) {
    if (State.variables.period >= 6)
        return "Pre Bed";
    return false;
}

(function () {
    const $popup = $(document.createElement('div'))
        .attr('id', 'imgPopUp')
        .on('click', () => $popup.removeClass('open'))
        .appendTo(document.body);

    $(document).on('click', 'img', (ev) => {
        /* make sure that the image is still on the page to account for image links */
        if (!document.body.contains(ev.target)) return;
        /* hopefully this will catch broken images */
        if (ev.target.naturalHeight == 0 || ev.target.naturalWidth == 0) return;

        $popup
            .css('background-image', `url('${ev.target.src}')`)
            .addClass('open');
    });

    $(document.head).append(`<style>
        #imgPopUp {
            display: none;
            position: fixed;
            inset: 0;
            z-index: 100200;
            background-color: rgba(0, 0, 0, 0.75);
            background-size: contain;
            background-position: center;
            background-repeat: no-repeat;
        }
        #imgPopUp.open {
            display: block;
        }
    </style>`);
}());
Just remove the line return false; So like this:
Code:
Config.navigation.override = function (dest) {
    if (State.variables.period >= 6)
        return "Pre Bed";
}
 

guest1492

Member
Apr 28, 2018
350
288
I'm pretty sure that the problem is still that you did not add a semicolon ; after the closing bracket } at the end of the navigation override function.

The first time you had an error is either from you splitting off the CSS improperly (I used JS to apply the CSS so you wouldn't have to worry about it), or it's the same problem of the missing semicolon except you had placed the JS in a different order, or it could be something else that was completely unrelated to the JS I provided.
 
  • Like
Reactions: Studio31

Alcahest

Engaged Member
Donor
Game Developer
Jul 28, 2017
3,484
4,330
I'm pretty sure that the problem is still that you did not add a semicolon ; after the closing bracket } at the end of the navigation override function.

The first time you had an error is either from you splitting off the CSS improperly (I used JS to apply the CSS so you wouldn't have to worry about it), or it's the same problem of the missing semicolon except you had placed the JS in a different order, or it could be something else that was completely unrelated to the JS I provided.
No need to add ; after functions declared the "normal" way, ie with a { } scope.
 
Last edited:
  • Like
Reactions: Studio31

guest1492

Member
Apr 28, 2018
350
288
No need to add ; after functions declared the "normal" way, ie with a { } scope.
True, but the problem here is that I'm also assigning that function to a variable. There's no semicolon behind it so JS will rely on automatic semicolon insertion, but that doesn't always work correctly.

What I think is happening is that the IIFE (the Immediately Invoked Function Expression that handles the "zoomed picture popup") that's immediately after is being taken as providing an argument for the function that is meant to be assigned as a navigation override.

Basically, let's say that I want to create an alias for Date.now().
JavaScript:
var now1 = Date.now;
But with the way the code was written, it's being taken as:
JavaScript:
var now2 = Date.now(some random gibberish);
So now1 is a function while now2 is the result of calling that function.
 

Alcahest

Engaged Member
Donor
Game Developer
Jul 28, 2017
3,484
4,330
True, but the problem here is that I'm also assigning that function to a variable. There's no semicolon behind it so JS will rely on automatic semicolon insertion, but that doesn't always work correctly.

What I think is happening is that the IIFE (the Immediately Invoked Function Expression that handles the "zoomed picture popup") that's immediately after is being taken as providing an argument for the function that is meant to be assigned as a navigation override.

Basically, let's say that I want to create an alias for Date.now().
JavaScript:
var now1 = Date.now;
But with the way the code was written, it's being taken as:
JavaScript:
var now2 = Date.now(some random gibberish);
So now1 is a function while now2 is the result of calling that function.
After some testing, I see that you're correct that it's the IIFE that messes things up. Removing the "return false" as I suggested worked only as long as the if statement before it was false because then the return value would be null/undefined, which works in this case, ie return null works even without any semicolon.

This automatic insertion of ; is all news to me but I see now that you can skip it everywhere -- until you can't.
 
  • Like
Reactions: Studio31

osanaiko

Engaged Member
Modder
Jul 4, 2017
2,548
4,634
This automatic insertion of ; is all news to me but I see now that you can skip it everywhere -- until you can't.
Just another of those "fun" JavaScript surprises. It's almost as though a (in hindsight a very smart but not infallible) coder pooped the whole language design out in 3 days after being threatened with job loss by the Netscape CEO. These days battle scarred JS coders just semi-colon every line, it's easier than worrying about the rare exception cases. (actually, these days true JS coders don't exist, it's all reactbros pulling 600MB of useless shite from NPM for a simple hello world. No, I'm not bitter.)
 
  • Haha
Reactions: Alcahest