Quests Feature Question - Applying Typewriter to the whole game [Alt-Solved] [By using built-in functions]

Hello,

I'd like to know if there is an easy way to apply the typewriter-display effect for the whole game ?
Or do I have no other choice than overloading the game with scripts to trigger it ?
If it needs a bit of programming to tweak this, I can do it but only with enough explanations.

Also, is it possible to add delays within a same message ? Maybe by using some weird-typewriter effect ?
Like, the game would run like this :

Hello ?[2 seconds delay]
Can you hear me ?[3 seconds delay]
Please answer..
[Player can now input its command]

In advance, thank you for your answers,

Lily Narwasereg


Hmm…

You can't override msg(), which Quest uses to send most of its text to the frontend, because it's a built-in function. However, you can override the javascript function addText, which is used by msg().

Off the top of my head, my first guess would be a piece of javascript that looks something like:

$(function () {
  var original_addText = addText;
  addText = function (text) {
    var element = $($.parseHTML(text));
    original_addText(element);
    element.typewriter(100);
  };
});

That applies the typewriter TextFX to the entire game… but it will have issues because the default typewriter doesn't allow formatting. I'm not sure how it would work with the modified typewriter script I posted recently; might be worth trying. But this probably needs a little more work before it's ready for use.


[Note: This isn't working yet, but I'm posting so that if anyone else can see the problems, they can fix it. Plus I don't have anywhere convenient to save a work-in-progress right now, so on the forum seems as good a place as any]

Edit: This seems to work.
To use it, either put it in a javascript file within the project (desktop version only) or put it on a single line in the game's UI initialisation script (game → 'Advanced scripts' tab) in the form: JS.eval("javascript goes here")

My second thought would be something like…

$(function () {
  var original_addText = addText;
  addText = function (text) {
    var done = getCurrentDiv().children().last()[0];
    original_addText(text);
    getCurrentDiv().find('*').contents().each(function () {
      if (this == done) {
        done = 0;
      } else if (!done) {
        if (this.nodeType == 3) {
          $(this).replaceWith($('<span>').data('typewritercontent', $(this).text()).attr('typewriterdelay', 0));
        }
      }
    });
  };

  setInterval (function () {
    var elem = $('*[typewriterdelay]').first();
    var text = elem.data('typewritercontent');
    if (text) {
      elem.append(text.substring(0,1));
      if (text.length > 1) {
        elem.data('typewritercontent', text.substring(1));
      } else {
        elem.removeData('typewritercontent');
      }
    }
    if (!text) {
      var delay = elem.attr('typewriterdelay');
      if (delay > 1) {
        elem.attr('typewriterdelay', delay - 1);
      } else {
        elem.removeAttr('typewriterdelay');
      }
    }
  }, 100);
});

Off the top of my head, that should avoid using the default typewriter effect, but do something similar to all text nodes in the output. You can then include something like <span typewriterdelay="10">The text will pause after this sentence!</span> in your text. The delay in this case being in tenths of a second (or characters for the typewriter).

I'm on my phone right now so can't test that. I'll have a look when I'm in a better position. It doesn't seem to work right now, but I think that's probably some silly mistake.


Thank you for the suggestions. I'm using the desktop version, so I just have to put your script inside of a file, name it blabla.js, and Quest will automatically detect and compile it ? (JS is not the language I know, I mainly know Python and Java)

I'd need to be able to change the font color. It's better to differentiate who is talking.

The goal is that, I want my game to break the 4th wall. The story is like, the user (You) is telling the guy inside of the game what he should do, like a robot. Therefore, I feel like the Typewriter effect gives a better atmosphere regarding "Communication"

So, if you or someone think of another alternative method to get the same effect, I'm good with that too. ^^


Does the script not work with coloured text? I can't see why that would happen.

Issues at present:

  • Sometimes it doesn't seem to run at a constant speed, and I'm not sure why
  • No ability to change the speed while it's running
  • Allows the player to enter commands without waiting for the typewriter to finish
  • Images appear immediately
  • Player could get frustrated waiting for it
  • Automatic scrolling is broken

I think all of those could be addressed, but some of them I think I'd have to experiment with a bit to get the desired effect.


I'm not saying the script doesn't work with coloured text, just that I'd want it to work with the color formatting.

Also you didn't answer my questions.

And it looks like it's hard to do what I want with the typewriter, if it is not possible then it's okay, I'll deal without it


My experience with older versions of Quest has shown that frequent use of the typewriter effect has caused the font to become slower and slower. Has this been fixed?


I'm using the desktop version, so I just have to put your script inside of a file, name it blabla.js, and Quest will automatically detect and compile it ?

I think so. Not entirely sure, because I don't use the desktop version.


Here's a top-of-my-head attempt to solve some of the issues I picked out before.

This version should display the "Continue" link (as for Quest's wait {} capability) when the typewriter is running. While it's typing, pressing the 'continue' button will fill in the rest of the typewriter text before clicking the real 'Continue' link.

The HTML passed to this function may use the following attributes (on any element):
typewriterspeed="80" (or any other number) - sets the number of milliseconds between letters. Speed will change at the start of this element.
typewriterdelay="5" (or any number) - after this element, pause for time equivalent to 5 letters.
typewriterstop="1" - pressing a key to skip typing the text will stop after this element, then continue typing at the same speed as before. You can put this immediately before a Quest wait to ensure that pressing a key to speed up the text doesn't prematurely end the wait; or to let the player skip through dialogue line-by-line.

(NOTE: Written off the top of my head, not yet tested)

$(function () {
  var reallyWaiting;
  var original_beginWait = beginWait;
  var original_endWait = endWait;
  beginWait = function () {
    reallyWaiting = true;
    original_beginWait();
  };
  endWait = function() {
    typeWriter_skip();
  };
  waitEnded = function () {
    reallyWaiting = false;
    typewriter_skip();
  };
  typewriter_skip = function () {
    var stopped = false;
    $('*[typewriterdelay]').each(function () {
      var text = $(this).data('typewritercontent');
      if (text) {
        $(this).append(text);
      }
      $(this).removeData('typewritercontent').removeAttr('typewriterdelay');
      if ($(this).attr('typewriterstop')) {
        stopped = true;
        return false
      }
    });
    _waitMode = (reallyWaiting || $('*[typewriterdelay]').length);
    if (!stopped) {
      if (reallyWaiting) {
        original_endWait();
      } else {
        $("#endWaitLink").hide();
        $("#txtCommand").show();
      }
    }
  };

  var typewriter_iterator = function () {
    var elem = $('*[typewriterdelay]').first();
    if (_waitMode && !reallyWaiting && !elem.length) {
      _waitMode = false;
      $("#endWaitLink").hide();
      $("#txtCommand").show();
    }
    if (elem.attr('typewriterspeed')) {
      clearInterval(typewriter_timer);
      setInterval(typewriter_timer, elem.attr('typewriterspeed'));
    }
    var text = elem.data('typewritercontent');
    if (text) {
      elem.append(text.substring(0,1));
      if (text.length > 1) {
        elem.data('typewritercontent', text.substring(1));
      } else {
        elem.removeData('typewritercontent');
      }
    }
    if (!text) {
      var delay = elem.attr('typewriterdelay');
      if (delay > 1) {
        elem.attr('typewriterdelay', delay - 1);
      } else {
        elem.removeAttr('typewriterdelay');
      }
    }
  };
  var typewriter_timer = setInterval(typewriter_iterator, 100);

  var original_addText = addText;
  addText = function (text) {
    var done = getCurrentDiv().children().last()[0];
    original_addText(text);
    textNodes = 0;
    getCurrentDiv().find('*').contents().each(function () {
      if (this == done) {
        done = false;
      } else if (!done) {
        if (this.nodeType == 3) {
          $(this).replaceWith($('<span>').data('typewritercontent', $(this).text()).attr('typewriterdelay', 0));
          textNodes++;
        }
      }
    });
    if (textNodes && !_waitMode) {
      original_beginWait();
    }
  };
});

Since this was way too complicated, I tried a few stuff with the inbuilt commands, and found one to handle this.

At least in Desktop Version, when you add a script, there is a type of script which is "Run script after a number of seconds".
With this, for each line that needs a seperate "typewriter", you add this Script Command.
And then, INSIDE of this Script Command, you add the Typewritter with the text needed.
The effect is then perfectly displayed ! It works really well.

Here is a picture that shows what I'm talking about. The text came random from my mind so please don't judge it, it's cliché xD

When the game is run, it's displayed as this :
[Enter Room]
[5 seconds of nothing]
"Hello, it is me...."
is shown in Typewriter mode
[5 seconds of nothing]
[Font color in red change for the next text, the previous ones remains default]
"I CAME TO KILL YOU"
is shown in Typewritter mode

Since this works perfectly for me, and has exactly the effect I needed without diving too deep into Javascript Shenanigans, I consider this to be the good Alternative Solution for me ^^

Thank you anyway for helping me !


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

Support

Forums