Quest 5.8 will have a new attribute on the game object: suppressturnscripts
, which is set to false by default.
The FinishTurn
function has been modified to check this value before calling RunTurnScripts
:
<function name="FinishTurn">
if (not GetBoolean(game, "suppressturnscripts")) {
RunTurnScripts
}
game.suppressturnscripts = false
UpdateStatusAttributes
CheckDarkness
UpdateObjectLinks
</function>
If you are scripting something which will cause the turn scripts to fire an extra time (like a call to ASLEvent), you can add this to the script to suppress the turn scripts once:
game.suppressturnscripts = true
Note that this will not prevent the turn scripts from firing when using in conjunction with a call to ASLEvent
. It will prevent the turn scripts from firing TWICE in one turn. This is because of the way ASLEvent
calls are setup. Initially, they were only used for sending commands when clicking on the buttons or the hyperlinks, so they are hard-coded to call FinishTurn
.
Also note that setting game.suppressturnscripts to true in a normal script (without a call to ASLEvent
or Handle*Command
, or something of that nature) will prevent the turn scripts from firing at all.
Confused yet?
Good! Now, let's add a turn count to the mix!
Sorry, online users! I will be overriding a Quest function in this code, and you can't do that. If you can't use the desktop version of Quest, reading any more of this will be a waste of your time. (This is only because of all of the crazy things I'm doing at once in this example game, mind you. I will make myself a note to post a different example for those of you using the web editor.)
Here is the game object in full code view:
<game name="Suppressing the Turn Scripts">
<gameid>65c36394-fcd4-4abf-89a5-4d0659cb4ef7</gameid>
<version>1.0</version>
<firstpublished>2018</firstpublished>
<feature_advancedscripts />
<turns type="int">0</turns>
<statusattributes type="stringdictionary">
<item>
<key>turns</key>
<value>Turns: !</value>
</item>
</statusattributes>
</game>
I have an integer attribute named "turns", which is initially set to 0.
<turns type="int">0</turns>
I also have a statusattributes
dictionary attribute set up on the game object:
<statusattributes type="stringdictionary">
<item>
<key>turns</key>
<value>Turns: !</value>
</item>
</statusattributes>
I have to set up a function which is called by a modified HandleSingleCommand
to make all of this work together correctly:
<function name="TurnCount">
if (not GetBoolean(game, "notarealturn")) {
IncreaseObjectCounter (game, "turns")
}
game.notarealturn = false
</function>
HandleSingleCommand
I simply add the line TurnCount
to the very end of the HandleSingleCommand
function's script.
If you'd like to see the entire function in code view, click here:
<function name="HandleSingleCommand" parameters="command"><![CDATA[
if (LCase(command) = "again" or LCase(command) = "g") {
// First handle AGAIN
if (not game.pov.currentcommand = null) {
HandleSingleCommand (game.pov.currentcommand)
}
else {
msg ("There is nothing to repeat.")
}
}
else {
// Check through all commands for any that match
candidates = NewObjectList()
foreach (cmd, ScopeCommands()) {
if (IsRegexMatch(cmd.pattern, command, cmd.name)) {
list add (candidates, cmd)
}
}
maxstrength = -1
thiscommand = null
// Pick the best match
foreach (candidate, candidates) {
strength = GetMatchStrength(candidate.pattern, command, candidate.name)
// favour commands defined later, so an author can override a library command...
if (strength >= maxstrength) {
// ... except if the command defined later (candidate) has no parent, and the current best
// match (thiscommand) does have a parent. We want to favour any commands defined in rooms
// over global candidates.
skip = false
if (thiscommand <> null) {
if (thiscommand.parent <> null and candidate.parent = null) {
skip = true
}
}
if (not skip) {
thiscommand = candidate
maxstrength = strength
}
}
}
if (thiscommand = null) {
if (HasScript(game, "unresolvedcommandhandler")) {
params = NewDictionary()
dictionary add (params, "command", command)
do (game, "unresolvedcommandhandler", params)
}
else {
msg (Template("UnrecognisedCommand"))
}
HandleNextCommandQueueItem
}
else {
varlist = Populate(thiscommand.pattern, command, thiscommand.name)
HandleSingleCommandPattern (command, thiscommand, varlist)
}
}
TurnCount
]]></function>
If I wish to suppress the turn count during out of world commands (such as HELP, HINT, etc.), I add this line to the command's script:
game.notarealturn = true
My TurnCount
function will automatically set game.notarealturn back to false when called, so the turn count will be increased (as it normally would) on the next turn (unless I suppress the turn count again).
Now I can suppress the turn scripts and the turn count, even while calling an ASLEvent.
I have four test commands to play with:
<command name="hint">
<pattern>hint;hints</pattern>
<script>
game.suppressturnscripts = true
game.notarealturn = true
msg ("This story has no hints.")
</script>
</command>
<command name="testone">
<pattern>test one</pattern>
<script>
JS.testOne ()
</script>
</command>
<command name="testtwo">
<pattern>test two</pattern>
<script>
game.suppressturnscripts = true
JS.testTwo ()
</script>
</command>
<command name="testthree">
<pattern>test three</pattern>
<script>
game.notarealturn = true
game.suppressturnscripts = true
JS.testThree ()
</script>
</command>
Note that the HINT command doesn't require anything extra, but each of the TEST commands are calling a JS function, each of which call an ASLEvent
, which each call a Quest function:
<function name="CallMeWithASL" parameters="data">
msg (data)
</function>
I would normally show how to do this in JS.eval()
, but, since we are already overriding functions to pull all of this off, we might as well just use the desktop player to our advantage and include a Javascript file.
<javascript src="javascript.js" />
javascript.js
// I am using a setTimeout so the text will actually print online.
// I am adding additional setTimout so the web player scrolls to the end after if finally decides to print the message.
function testOne(){
setTimeout(function(){
ASLEvent('CallMeWithASL','The turn scripts fired twice!');
if (webPlayer){
setTimeout(function(){
scrollToEnd();
},500);
}
},1);
};
function testTwo(){
setTimeout(function(){
ASLEvent('CallMeWithASL','This did not cause the turn scripts to fire an extra time. The turn scripts only fired once, as expected.');
if (webPlayer){
setTimeout(function(){
scrollToEnd();
},500);
}
},1);
};
function testThree(){
setTimeout(function(){
ASLEvent('CallMeWithASL','This did not cause the turn scripts to fire an extra time, and the turn count stayed the same.');
if (webPlayer){
setTimeout(function(){
scrollToEnd();
},500);
}
},1);
};
It's very boring and dumb, but it's working correctly.
http://textadventures.co.uk/games/view/wojva_z2wu2hh5r8kiernq/suppressing-the-turn-scripts
The Code:
<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Suppressing the Turn Scripts">
<gameid>65c36394-fcd4-4abf-89a5-4d0659cb4ef7</gameid>
<version>0.5</version>
<firstpublished>2018</firstpublished>
<feature_advancedscripts />
<turns type="int">0</turns>
<statusattributes type="stringdictionary">
<item>
<key>turns</key>
<value>Turns: !</value>
</item>
</statusattributes>
<description><![CDATA[A test game.<br/><br/>Enter HINT: no turn scripts, and no turn count<br/><br/>Enter TEST ONE: turn scripts fire twice in one turn, and the turn count increases by 2<br/><br/>Enter TEST TWO: turns scripts fire once, and the turn count increases by 1<br/><br/>Enter TEST THREE: no turn scripts, and no turn count]]></description>
<author>KV</author>
</game>
<turnscript name="test_turnscript">
<enabled />
<script><![CDATA[
msg ("<b><center><br/>I AM THE TEST TURNSCRIPT!<br/></center></b>")
]]></script>
</turnscript>
<object name="room">
<inherit name="editor_room" />
<description><![CDATA[<br/>Enter (or click):<br/> {command:TEST ONE}, {command:TEST TWO}, or {command:TEST THREE}]]></description>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
<command name="hint">
<pattern>hint;hints</pattern>
<script>
game.suppressturnscripts = true
game.notarealturn = true
msg ("This story has no hints.")
</script>
</command>
<command name="testone">
<pattern>test one</pattern>
<script>
JS.testOne ()
</script>
</command>
<command name="testtwo">
<pattern>test two</pattern>
<script>
game.suppressturnscripts = true
JS.testTwo ()
</script>
</command>
<command name="testthree">
<pattern>test three</pattern>
<script>
game.notarealturn = true
game.suppressturnscripts = true
JS.testThree ()
</script>
</command>
<function name="HandleSingleCommand" parameters="command"><![CDATA[
if (LCase(command) = "again" or LCase(command) = "g") {
// First handle AGAIN
if (not game.pov.currentcommand = null) {
HandleSingleCommand (game.pov.currentcommand)
}
else {
msg ("There is nothing to repeat.")
}
}
else {
// Check through all commands for any that match
candidates = NewObjectList()
foreach (cmd, ScopeCommands()) {
if (IsRegexMatch(cmd.pattern, command, cmd.name)) {
list add (candidates, cmd)
}
}
maxstrength = -1
thiscommand = null
// Pick the best match
foreach (candidate, candidates) {
strength = GetMatchStrength(candidate.pattern, command, candidate.name)
// favour commands defined later, so an author can override a library command...
if (strength >= maxstrength) {
// ... except if the command defined later (candidate) has no parent, and the current best
// match (thiscommand) does have a parent. We want to favour any commands defined in rooms
// over global candidates.
skip = false
if (thiscommand <> null) {
if (thiscommand.parent <> null and candidate.parent = null) {
skip = true
}
}
if (not skip) {
thiscommand = candidate
maxstrength = strength
}
}
}
if (thiscommand = null) {
if (HasScript(game, "unresolvedcommandhandler")) {
params = NewDictionary()
dictionary add (params, "command", command)
do (game, "unresolvedcommandhandler", params)
}
else {
msg (Template("UnrecognisedCommand"))
}
HandleNextCommandQueueItem
}
else {
varlist = Populate(thiscommand.pattern, command, thiscommand.name)
HandleSingleCommandPattern (command, thiscommand, varlist)
}
}
TurnCount
]]></function>
<function name="TurnCount">
if (not GetBoolean(game, "notarealturn")) {
IncreaseObjectCounter (game, "turns")
}
game.notarealturn = false
</function>
<function name="FinishTurn">
if (not GetBoolean(game, "suppressturnscripts")) {
RunTurnScripts
}
game.suppressturnscripts = false
UpdateStatusAttributes
CheckDarkness
UpdateObjectLinks
</function>
<function name="CallMeWithASL" parameters="data">
msg (data)
</function>
<javascript src="javascript.js" />
</asl>
NOTE: I didn't use a turn script for the turn count because the ASLEvent caused it to increase no matter what I did. In the end, I decided HandleSingleCommand
was probably the best place to put it, anyway.
These commands should suppress turn scripts:
oops
help
save
version
log
all transcript commands