HTML Can anyone with more javascript experience please help me to figure out what this function is doing?

Apr 25, 2019
93
371
Solved thanks to outsider artisan! I'll keep this up in case someone else has a similar problem in the future.

Im just gonna post the code up front but if you want more info read below.

JavaScript:
// Function 1 - the main one of concern here
window.harvest = function (t, n, i) {
        void 0 === window.sources[t] && (window.sources[t] = i || 5), window.sources[t] -= n, window.sources[t] < 0 && (n += window.sources[t], window.sources[t] = 0), window.mc.sissy += n
}

// Rewritten for readability (at least this is how im trying to interpret it)
window.harvest = function (t, n, i) {
        void 0 === window.sources[t] && (window.sources[t] = i || 5),
        window.sources[t] -= n,
        window.sources[t] < 0 && (n += window.sources[t],
        window.sources[t] = 0),
        window.mc.sissy += n
}

// Function 2 - that window.sources it's referencing (comes before func 1)
window.sources = {}

// How these funcs are called in the game code
window.harvest('washroom', 1, 8)
window.harvest('porn', 0.5)
Ive been in the process of porting an abandoned HTML game from Twine Snowman to Sugarcube as a way of teaching myself Twine & Sugarcube (dont worry you shouldnt have to know anything about twine/sugarcube to help with this). Ive worked with javascript before but it was maybe 6 years ago at this point (C++/python are my main forte). Tldr the game deals with sissification (so this is an important mechanic) and while i have a temporary solution in place (im just skipping right to that window.mc.sissy += n line), Id like to figure out whats this is doing in order to keep the game as close to the original at least.
I understand bits and pieces of this but the whole void 0 === window.sources[t] part and window.sources[t] < 0 && (n += window.sources[t], window.sources[t] = 0) completely throw me off.
Id try an ask the dev of the abandoned game but they havent logged into tfgames in months so that doesnt seem like itll be possible. Any help would be appreciated but if you cant figure it out either, no worries. Just figured id ask here before i go about spending hours trying to figure it out myself manually.
 
Last edited:

outsider artisan

Developer of Succubus Stories.
Game Developer
Jun 14, 2020
367
633
AFAIK void 0 === X is a silly way of saying undefined === X. The line of code there could be written as

JavaScript:
if (window.sources[t] === undefined) {
    window.sources[t] = i || 5; // in other words use i unless i is falsy (0 or undefined), in which case, use 5
}
This code looks like it might have been run through a minifier, so that's maybe why it's so unreadable.

&& and || can be used sort of like quick conditionals in JavaScript; if I say condition && expression, then the expression will only run if the condition is true, because if it's false, JavaScript will immediatelystop processing the conditional once is hits the && if the first part was false, since the whole statement is false. Once you hit a comma, that's sort of like a semicolon in that the statement ends and the next one begins. There is no real reason to use commas over semicolons I can see in this code specifically, so again, that just seems like evidence maybe of a minifier at work.

Near as I can tell, the code is something like:

JavaScript:
window.harvest = function harvest (t, n, i) { // always name your functions so errors will identify them
 
  if (window.sources[t] === undefined) {
    window.sources[t] = i || 5; // in other words use i unless i is falsy (0 or undefined), in which case, use 5
  }
  window.sources[t] -= n;

  if (window.sources[t] < 0) {
    n += window.sources[t];
    window.sources[t] = 0;
  }

  window.mc.sissy += n;

}
Something like that. That looks a little rickety to me, like it's more logic than is strictly necessary, but I don't want to try to over-engineer it since I'm sure you have your own preferences for how the code should look. I also didn't test the code, so it's possible the original or my version contains errors, but I believe it is correct in concept.
 
Last edited:
Apr 25, 2019
93
371
AFAIK void 0 === X is a silly way of saying undefined === X. The line of code there could be written as

JavaScript:
if (window.sources[t] === undefined) {
    window.sources[t] = i || 5; // in other words use i unless i is falsy (0 or undefined), in which case, use 5
}
This code looks like it might have been run through a minifier, so that's maybe why it's so unreadable.

&& and || can be used sort of like quick conditionals in JavaScript; if I say `condition && expression`, then the expression will only run if the condition is true, because if it's false, JavaScript will immediatelystop processing the conditional once is hits the && if the first part was false, since the whole statement is false. Once you hit a comma, that's sort of like a semicolon in that the statement ends and the next one begins. There is no real reason to use commas over semicolons I can see here, so again, that just seems like evidence maybe of a minifier at work.

Near as I can tell, the code is something like:

JavaScript:
window.harvest = function harvest (t, n, i) { // always name your functions so errors will identify them
  
  if (window.sources[t] === undefined) {
    window.sources[t] = i || 5; // in other words use i unless i is falsy (0 or undefined), in which case, use 5
  }
  window.sources[t] -= n;

  if (window.sources[t] < 0) {
    n += window.sources[t];
    window.sources[t] = 0;
  }

  window.mc.sissy += n;

}
Something like that. That looks a little rickety to me, like it's more logic than is strictly necessary, but I don't want to try to over-engineer it since I'm sure you have your own preferences for how the code should look. I also didn't test the code, so it's possible it contains syntax errors, but I believe it is correct in concept.
Wow! Thanks for this great explanation and quick reply. (so great it broke the site, at least for me lol)

&& and || can be used sort of like quick conditionals in JavaScript
Never heard of this before but i imagine it must be another kind of ternary operator (like doing Condition ? If true : If false). ill have to look into that more tomorrow.

This code looks like it might have been run through a minifier
And yeah i figured as much also. All the javascript is like this although idk if the dev did that themself or if it's something twine did due to me working off of a release copy and not the source code (although id venture to guess its more likely the latter).

Thanks again for all this
 

outsider artisan

Developer of Succubus Stories.
Game Developer
Jun 14, 2020
367
633
Never heard of this before but i imagine it must be another kind of ternary operator (like doing Condition ? If true : If false). ill have to look into that more tomorrow.
The ternary operator is sort of a one line conditional, the way the logical operators work allows them to be used like conditionals too, but that can lead to a lot of hard to read run-on conditionals, like what you had here, so it's probably best avoided. var x = y || 1; is pretty common though. It's called .

And yeah i figured as much also. All the javascript is like this although idk if the dev did that themself or if it's something twine did due to me working off of a release copy and not the source code (although id venture to guess its more likely the latter).
Twine itself definitely does not minify code, so I imagine the developer did this themselves, probably by using something like and setting up their own toolchain, which I expect to be the case because I do the same thing. It's also possible they just cut-n-pasted the code in and out of a minifier or something, though, I suppose.

Thanks again for all this
You're welcome, and good luck!
 
  • Like
Reactions: gojira667
Apr 25, 2019
93
371
It's called .
Oh i dont think ive heard of these before. Ill have to look into this for sure then.

which I expect to be the case because I do the same thing
A bit off topic but is there any reason why someone would do that? Slow runtimes or large file sizes maybe? Or are you talking about using Tweego? (which i will also have to look into lol) I only ask because im maybe about halfway through getting this sugarcube build up to where the game was when it was abandoned and i havent personally had a problem with run times or the exported html file being too big yet (although in the latter case if youre including a large folder of pics and videos i dont know if that would really matter all that much either, that is if your end user is already downloading a big zip id imagine html files would compress quiet easily compared to pics or videos and so file size wouldnt matter much)
 

outsider artisan

Developer of Succubus Stories.
Game Developer
Jun 14, 2020
367
633
Oh i dont think ive heard of these before. Ill have to look into this for sure then.


A bit off topic but is there any reason why someone would do that? Slow runtimes or large file sizes maybe? Or are you talking about using Tweego? (which i will also have to look into lol) I only ask because im maybe about halfway through getting this sugarcube build up to where the game was when it was abandoned and i havent personally had a problem with run times or the exported html file being too big yet (although in the latter case if youre including a large folder of pics and videos i dont know if that would really matter all that much either, that is if your end user is already downloading a big zip id imagine html files would compress quiet easily compared to pics or videos and so file size wouldnt matter much)
I'm personally more comfortable using a code editor, I think the editor that is built into Twine is not super good for heavier coding. There's also that has SugarCube syntax highlighting, code completion, snippets, etc which is nice. Oddly, SugarCube did not have syntax highlighting at all in the Twine editor last time I used it, that may have changed since. I am also using heavily customized tools, like a custom story format and a modified version of Tweego to make my game, so that feeds into me using Tweego, since it's easier for me to customize and integrate with other tools and stuff.

There are certainly benefits to Tweego, but I personally didn't switch because of any major deficiency in the Twine program itself other than what I said about the code editor and syntax highlighting. My expectation is that Twine performs totally fine.

You don't have permission to view the spoiler content. Log in or register now.
 
Apr 25, 2019
93
371
I'm personally more comfortable using a code editor, I think the editor that is built into Twine is not super good for heavier coding. There's also that has SugarCube syntax highlighting, code completion, snippets, etc which is nice. Oddly, SugarCube did not have syntax highlighting at all in the Twine editor last time I used it, that may have changed since. I am also using heavily customized tools, like a custom story format and a modified version of Tweego to make my game, so that feeds into me using Tweego, since it's easier for me to customize and integrate with other tools and stuff.

There are certainly benefits to Tweego, but I personally didn't switch because of any major deficiency in the Twine program itself other than what I said about the code editor and syntax highlighting. My expectation is that Twine performs totally fine.

You don't have permission to view the spoiler content. Log in or register now.
Thanks again for this. The editor for twine is certainly a weak point so it's something ill have to look into at some time in the future. Didnt hear about the vscode plugin (i think i heard theres one for notepad++ though) so maybe i can end up looking into that also if i think of it.

that may have changed since
and no theres still no syntax highlighting lol

I wanted as much compression as possible to make the game as small as possible to optimize for playing on the web
Im guessing thisll have to be a thing where ill have to have some playtesters and see if anyones having a problem running it as is and then go from there
 

outsider artisan

Developer of Succubus Stories.
Game Developer
Jun 14, 2020
367
633
Im guessing thisll have to be a thing where ill have to have some playtesters and see if anyones having a problem running it as is and then go from there
I don't think you'll have to worry about it. My game is very large, and by the time it's done it will be even larger. Decompression isn't free, but if the game is large enough, the time it takes to decompress will be lower than the time it takes to download when played on the web.

I think a lot of very large Twine games are designed to be downloaded as a zip and played locally. I just wanted to make sure my game would be a reasonably good experience when played on the web even at like 3G speeds.

It's probably premature optimization for most games though. I'm not really talking about it because I think you should do it, just as an explanation for why I have such limited experience with the Twine program itself.

Didnt hear about the vscode plugin (i think i heard theres one for notepad++ though) so maybe i can end up looking into that also if i think of it.
I think VSCode is a great code editor, but if you prefer NP++, I'm sure that syntax highlighter works too. There's also one for Atom and one for Sublime. The VSCode one is very advanced and has a lot of features compared to the others I've used though, so definitely worth trying out. It can be a bit of a pain to setup, though.
 

Rafster

Bear chaser
Game Developer
Mar 23, 2019
2,099
4,087
I'm always trying to learn new things, and I also happen to work with twine/sugarcube. What does that object
Code:
window
do? I only know the basics of javascript.
 
Apr 25, 2019
93
371
I'm always trying to learn new things, and I also happen to work with twine/sugarcube. What does that object
Code:
window
do? I only know the basics of javascript.
Im gonna be honest, Im not 100% sure as this is a feature of the original game and not Twine SugarCube (which is what im porting the game to), but my best explanation is that window is an that holds everything else in the game and it is sort of the top of the game's hierarchy, if that make sense.

Basically by accessing the window part of the hierarchy you can create public functions (compared to if you were to make a function like you normally would in javascript function MyFunction() { //Func goes here }). That latter code would be how youd create private functions.

On top of this, window holds everything else in the game, including variables, which you can access using dot notation (see the link above if you're unfamiliar with this term). For example window.mc holds all the variables related to the player character in this game and window.story holds all the story related variables (like metXCharacter or something like that). I should note that im not sure if this is a native feature of Twine Snowman as the original developer of this game initialized most of the game variables through javascript (which might be why they're on the window object. Twine Snowman might default to storing variables on window.story, im not sure).

Now in Twine SugarCube you could also define public variables in the window object in the exact same way as above but when I looked into this before, . Instead you declare public variables in SugarCube by doing this instead:
JavaScript:
setup.MyFunction = function MyFunction () {
    // function goes here
}
Lastly now, in SugarCube you can't access variables through the window object (at least afaik). Instead you use SugarCube.state.variables or SugarCube.state.active.variables (I honestly don't know what the difference is). If you're writing code inside the story javascript part of your Twine though, you can omit the "SugarCube" part of these. For example:
JavaScript:
setup.AddMoney = function AddMoney (amount) {
    state.active.variables.money += amount;
  
    // Don't let player money go below $0
    if (state.active.variables.money <= 0){
        state.active.variables.money = 0;
    }
}
Hope this answers some questions. Im not an expert on javascript or Twine either as i explained above but this is everything i know to the best of my knowledge. If theres something wrong with this maybe someone more knowledgeable will be able to reach out and correct me.
 
Last edited:
  • Like
Reactions: Rafster

Rafster

Bear chaser
Game Developer
Mar 23, 2019
2,099
4,087
Hope this answers some questions. Im not an expert on javascript or Twine either as i explained above but this is everything i know to the best of my knowledge. If theres something wrong with this maybe someone more knowledgeable will be able to reach out and correct me.
Thank you man, yeah, that object sounded really weird to me, since in sugarcube I use the States.variables and States.temporary objects for the variables.
 
Apr 25, 2019
93
371
I'm personally more comfortable using a code editor, I think the editor that is built into Twine is not super good for heavier coding. There's also that has SugarCube syntax highlighting, code completion, snippets, etc which is nice. Oddly, SugarCube did not have syntax highlighting at all in the Twine editor last time I used it, that may have changed since. I am also using heavily customized tools, like a custom story format and a modified version of Tweego to make my game, so that feeds into me using Tweego, since it's easier for me to customize and integrate with other tools and stuff.

There are certainly benefits to Tweego, but I personally didn't switch because of any major deficiency in the Twine program itself other than what I said about the code editor and syntax highlighting. My expectation is that Twine performs totally fine.

You don't have permission to view the spoiler content. Log in or register now.
Ive only been messing around with tweego and that vscode extension for a few minutes but holy cow this is so much better than twine lol. Thanks again for putting me on to this!
 
  • Like
Reactions: outsider artisan
Sep 4, 2020
91
47
I stitched together a development environment in Intellij's WebStorm that works like this:

  1. I write code in TypeScript (superset of ES6 that incorporates static typing and other high-level language features)
  2. I write web styling in SASS/SCSS (specifically SCSS). SCSS is a superset of CSS that provides a more structured and programmatic way to do styling.
  3. I use Gulp, Babel, Dart SASS, Autoprefixer, PostCSS, and other npm-managed tools to compile the TypeScript into JavaScript (ES6) and SCSS into CSS. Gulp copies the resulting files into a build space.
  4. In parallel, I write Sugarcube-compliant twee files, also in WebStorm. The Gulp process also copies those files into the build space.
  5. Gulp runs Tweego against the build space (which only contains Twee files, JavaScript files, and CSS files, which are the only files Tweego understands) and directs the output (the game HTML file) into a distribution directory.
  6. Gulp also copies the image files into the distribution directory (into an images subdirectory).
  7. The distribution directory has the finished product, ready for play.

All this happens with a click of a button, because scripts! I'm describing it so you can get a sense of what the pieces are of a modern web development workflow (Gulp, Babel, SCSS, Nodejs, npm, and so on). Developing a Twine game is really just developing a web app. You might want to do some research into some of these topics and see how they can help you.

I was lucky in that I knew this stuff before goofing with Twine, so Twine was the only new thing for me.

And as for "void 0", yes, as mentioned, it is a safe way of saying "undefined". So why not say "undefined"? Well, because "void 0" *always* means undefined. However, "undefined" is a property of the global object, and properties can be redefined. I could change "undefined" to be a function that prints "Hello world" to the console. No one in their right mind would redefine "undefined", but it could happen. Fact is, most JavaScript programmers might not even know it's possible to redefine it. But a smart programmer would play it safe and use "void 0".

Having said that...

I've never used "void 0", and I'm pretty smart. If you see "void 0", I'd bet dollars to donuts this is machine-generated code. Remember how in Step 1 above I write in TypeScript and have Babel transpile that into JavaScript? That happens all the time in modern web development. TypeScript to ES6, or ES6 to ES5, or CoffeeScript to ES3, and so on and so forth -- all sorts of paths programmers take depending on what language they like to program in and what browsers they are targeting to support their app. If you look at that machine-generated code, you see those weird constructions all over the place.
 
Last edited:
Apr 25, 2019
93
371
I stitched together a development environment in Intellij's WebStorm that works like this:

  1. I write code in TypeScript (superset of ES6 that incorporates static typing and other high-level language features)
  2. I write web styling in SASS/SCSS (specifically SCSS). SCSS is a superset of CSS that provides a more structured and programmatic way to do styling.
  3. I use Gulp, Babel, Dart SASS, Autoprefixer, PostCSS, and other npm-managed tools to compile the TypeScript into JavaScript (ES6) and SCSS into CSS. Gulp copies the resulting files into a build space.
  4. In parallel, I write Sugarcube-compliant twee files, also in WebStorm. The Gulp process also copies those files into the build space.
  5. Gulp runs Tweego against the build space (which only contains Twee files, JavaScript files, and CSS files, which are the only files Tweego understands) and directs the output (the game HTML file) into a distribution directory.
  6. Gulp also copies the image files into the distribution directory (into an images subdirectory).
  7. The distribution directory has the finished product, ready for play.

All this happens with a click of a button, because scripts! I'm describing it so you can get a sense of what the pieces are of a modern web development workflow (Gulp, Babel, SCSS, Nodejs, npm, and so on). Developing a Twine game is really just developing a web app. You might want to do some research into some of these topics and see how they can help you.

I was lucky in that I knew this stuff before goofing with Twine, so Twine was the only new thing for me.

And as for "void 0", yes, as mentioned, it is a safe way of saying "undefined". So why not say "undefined"? Well, because "void 0" *always* means undefined. However, "undefined" is a property of the global object, and properties can be redefined. I could change "undefined" to be a function that prints "Hello world" to the console. No one in their right mind would redefine "undefined", but it could happen. Fact is, most JavaScript programmers might not even know it's possible to redefine it. But a smart programmer would play it safe and use "void 0".

Having said that...

I've never done used "void 0", and I'm pretty smart. If you see "void 0", I'd bet dollars to donuts this is machine-generated code. Remember how in Step 1 above I write in TypeScript and have Babel transpile that into JavaScript? That happens all the time in modern web development. TypeScript to ES6, or ES6 to ES5, or CoffeeScript to ES3, and so on and so forth -- all sorts of paths programmers take depending on what language they like to program in and what browsers they are targeting to support their app. If you look at that machine-generated code, you see those weird constructions all over the place.
Thank you for all this info! I havent done any serious "web development" in many years (iirc last time i did anything with web apps was back in the early hayday of ruby on rails) so i am very out of the loop. Ill have to look into some of this stuff to see how i might be able to integrate it into my workflow. ive written a python script or two which has helped speed stuff up along side switching form twine to tweego/vscode but my workflow could absolutely be streamlined even further.
 

HiEv

Member
Sep 1, 2017
384
785
Oddly, SugarCube did not have syntax highlighting at all in the Twine editor last time I used it, that may have changed since.
FYI - It's not really that odd, since only Harlowe does that, and it does it by using a hack.

Twine v2.4.x is in the works though and, IIRC, it sounds like it will have added an official method for syntax highlighting. Once that comes out, then the SugarCube developer, TheMadExile, can put in syntax highlighting code for that story format.
 
  • Like
Reactions: outsider artisan

outsider artisan

Developer of Succubus Stories.
Game Developer
Jun 14, 2020
367
633
FYI - It's not really that odd, since only Harlowe does that, and it does it by using a hack.

Twine v2.4.x is in the works though and, IIRC, it sounds like it will have added an official method for syntax highlighting. Once that comes out, then the SugarCube developer, TheMadExile, can put in syntax highlighting code for that story format.
Thank you, I wasn't sure of the internal reasons. I do still think it's odd for users. It makes it seem like SugarCube is somehow incomplete by comparison. I'm glad it's being addressed as I'm sure that first impression compared to Harlowe turns some people off what is otherwise by far the best runtime for Twine.