Hello!
I have a piece of code that looks like this:
<<linkreplace "The war took everything.">>\
<<type 30ms none>>\
<<linkreplace "From me, from everybody.">>\
<<type 30ms none>>\
[[Those of us left are only shells of our former selves; of what humanity once was.->War2]]
<</type>>\
<</linkreplace>>\
<</type>>\
<</linkreplace>>\
I want to make it so the player can click once for the typewriter effect to skip ahead. A potential problem with this is that if the text is clicked, even while the typewriter is executing, the text will be replaced by the following <<linkreplace>> (also at a delay, since it waits for the previous text to finish typing, even though it is no longer visible.)
My idea is that there needs to be some kind of check to make sure all text is displayed before it becomes a link. I played around with the t8n-typewriter module which skips the text once the space bar is pressed, however I understand that players may not want to go back and forth between the mouse and keyboard.
Alternatively, instead of having <<linkreplace>> at all, an arrow could appear at the bottom right of the content box once the text has finished typing/once the player has skipped the text, and instead act as the link to the next text and/or passage. This would allow the player to click anywhere in the content box to skip the text, then click the arrow once they are ready, which would replace the text with the next line or passage.
Unfortunately, I am not super sure how to execute either of these ideas. Perhaps they are wildly inefficient ways of going about this. If anyone has any solutions or advice, I would appreciate it a lot!
Placing the following into your projectâs Story JavaScript will cause clicks upon typing sections to finish, just the same as hitting the skip key would.
(function () {
var skipKeyEv = jQuery.Event('keydown', {
key : Config.macros.typeSkipKey
});
jQuery(document).on(':typingstart', function (ev) {
jQuery(ev.target).one('mousedown', function (ev) {
ev.stopImmediatePropagation();
ev.preventDefault();
jQuery(document.body).trigger(skipKeyEv);
});
});
})();
Awesome, thank you so much!! This is almost perfect, but I am wondering if it would be possible to click anywhere in the content box instead of just where the text will follow. Here is what my box looks like:
The text will only skip if I click somewhere the text will end up after typing. Some of my links are short sentences, so this may be frustrating for the player who is just clicking blindly hoping for the text to skip.
Thank you again! Apologies for any unclear language, I struggle explaining things succinctly.
Sorry to topple onto this, but I am having another related issue. I would like the link to only work if the text has finished typing, in order to avoid the player clicking unfinished typed text and accidentally skipping to the next section. As it is now, if I click on an area that has not finished typing but my click falls on the visible typed area, it skips to the next <<linkreplace>> or passage entirely. Sorry if this does not make senseâI can provide a visual or sample of code if needed.
Before going farther with this. Is this something youâre going to use sparingly or are you attempting to have a VN-style interface for most, or all, of your text?
If itâs the latter, then youâd probably be much better served by using the third-party Click To Proceed (CTP) macro set as VN-style interfaces are what itâs designed to do.
CTP-based Example
Hereâs what your current example could look like using CTPâand an optional helper widget that isnât necessary but simplifies things.
Example CTP usage (w/ helper widget):
<<ctp "vn-text" clear>>\
<<vntype>>\
The war took everything.
<</vntype>>
<<ctpNext>>\
<<vntype>>\
From me, from everybody.
<</vntype>>
<<ctpNext>>\
<<vntype "War2">>\
Those of us left are only shells of our former selves; of what humanity once was.
<</vntype>>
<</ctp>>
Example <<vntype>><</vntype>> helper widget code:
/*
<<vntype [passageName]>> ⌠<</vntype>>
- passageName: (optional) Name of the passage to send the player to
Examples:
<<vntype>>Text to type.<</vntype>>
<<vntype "Next passage">>Text to type.<</vntype>>
*/
<<widget "vntype" container>>
\<<type 30ms none>>
\<<= _contents.trim()>>
\<span class="vn-link"><<link "Continue">>
<<if _args[0]>>
<<goto _args[0]>>
<<else>>
<<ctpAdvance "vn-text">>
<</if>>
<</link>></span>
\<</type>>
\<</widget>>
Example <<vntype>><</vntype>> continue link style:
The latter is true, yes, though there will be instances within the game where the player must choose from a set of options rather than clicking a ânextâ button, which shouldnât be a problem to reformat for.
This macro set is actually beyond perfectâI cannot thank you enough for showing it to me and also writing the example code!!
Unfortunately, its been some time since Iâve touched coding, and I am especially dense with JavaScript, so I am having some difficulty implementing the helper widget. Specifically this part:
I read this and understand what it is meant to do (that is, I believe it is trying to check if the last section of âvn-textâ is being shown, and if so, go to the next passage when clicked) however I am unsure of what to plug in as the arguments to execute this. I also cannot figure out what <<_contents.trim()>> is used for, despite looking through the docs and other JS resources. Again, sorry if this is just super obvious, I hate to be the âcode for me/teach me everything!â guy.
I also understand that the helper widget is optional, so I tried to find a workaround using just the macro set itself, however I ran into essentially the same problem: I cannot figure out how to make the last section of âvn-textâ/the CTP container link to the next passage entirely using the ď¸ continue link. I feel like the solution is so simple but I canât grasp it.
Thank you again for any further help, this is already way further than I would have gotten on my own!
Itâs already implemented, so all you need to do is place it within a new passage that is tagged widget. Unless you meant modifying it?
Thatâs not quite correct. It checks to see if a passage name was passed to the widgetâe.g., <<vntype "War2">>âŚ.
If no passage name was given, the link it creates calls <<ctpAdvance "vn-text">> to advance to the next CTP case. If a passage name was given, the link it creates calls <<goto>> to send the player to that passage.
You can see this in my previous example where all of the <<vntype>> calls do not include a passage name except for the last one <<vntype "War2">>. Youâll generally only want your final case to include a passage name argument.
You have a typo there, itâs <<= _contents.trim()>>.
In order:
The <<=>> macro is a shorthand alias for the <<print>> macro.
As noted in the <<widget>> macro docs, the special temporary variable _contents holds the contents of container widgetsâi.e., whatâs between the opening and closing tags.
Yep, sorry, I misread a critical piece of info on the docs and started overthinking stuff. All good here.
Thank you for your excellent explanation! That now makes perfect sense and I see what I was misunderstanding.
Thank you so much for breaking down that line of code, I definitely understand it a lot better now. Unfortunately I am getting this error regarding it:
Error: <<=>>: bad evaluation: State.temporary.contents is undefined
I tried messing around with it using what I found on the docs and older forum posts but it only leads to other stuff breaking. I understand a variable cannot be called upon before it is defined, but I thought that the contents of the passage were what it would refer toâŚbut I guess since the widget passage is loaded first, it doesnât even get there. Iâm probably overthinking or missing something huge again, sorry.
The special _contents temporary variable is only defined for container widgetsâi.e., those created with the container keyword. The <<vntype>> widget definition does have the keyword, so _contentsshould be defined within it.
What version of SugarCube are you using? The version required for container widgets is âĽv2.36.0 and the current release is v2.36.1, which has been out for about two years.
EDIT: Forgot to reply to this:
The special _contents temporary variable contains the contents of the container widgetâs bodyâi.e., what it wraps. For example, in the following <<vntype>> call:
<<vntype>>\
The war took everything.
<</vntype>>
The _contents variable within the widget will hold The war took everything..
This is what I assumed too, but I was unaware that the container widget is supposed to define _contents. That area in the docs now makes a lot more sense, and it explains why everything I tried to do to fix it was just making it worse.
I thought it could have been another stray piece of code somewhere interfering, but creating a new story and testing it isolated yields the same results.
I should be using 2.36.1, as it is says in my story format page.
Ooh! I could see what it was doing, but not the steps in which it was taking to get to that point. That process makes sense now, thank you!