Easiest way to interrupt the command queue?

Hello.

Lets say I have a game with a butt-load of turn scripts. (Okay?)

Sometimes, one of the turn scripts might print something. Sometimes, none of them will. (With me so far?)

Now, occasionally, when a turn script does print something, the text is something important. Like, it might be telling you that a one-eyed, one-horned, flying, purple people-eater just came out of the sky and lit in a tree. Such information might make an adventurer want to take different action than originally intended, and it would be polite to stop all the pending actions, if any exist.

Or, say there's a random chance an adventurer might fall through a trap door after entering a certain room, but this is unbeknownst to the player. Plus, the player just travelled through that room last time but forgot to save the game. So, the player knows that N.W.E.GET LAMP.D.D should get them from the current location to the place they were last time (with lamp in hand), but this time they fall through the trap door after going west. On top of this, something in the darkness below the trap door asks you a question (WHAT?!?! IS YOUR FAVOURITE COLOUR???), and this particular something was very ornery and felt that any answer other than a colour (no matter which colour) was punishable by death?

Well, normally that command (N.W.E.GET LAMP.D.D) would go like this (I'll spread them out into single commands so you can see the process):

>N
You are in front of The Super-Spreader.

You can see topless dancers here.

You can go west or south.

>W
You go west.

You are in front of The Manhattan Restaurant of the Mind.

You can see Jake Chambers here.

Suddenly, you hear a strange noise coming from the sewer grate beneath your feet. Before you have time to register that you are looking at a pair of glowing, yellow eyes, whatever it is down there reaches up and snatches you down into the sewer!

It is pitch black.

The thing with the yellow eyes speaks. "WHAT?!?!" it groans, "IS YOUR FAVOURITE COLOUR???"

>E
"NOT A COLOUR!!!" The thing is shrieking, possibly laughing, as its eyes grow larger and closer to you. You can smell the thing's foul breath just before it reaches in, rips your heart out of your chest, and eats it right in front of you.

    **** You have died. ****

>GET LAMP
You stay out of this, you're dead. A silver spaceship improbably appears with a BAMF! It lights up the sewer. The shadow of the yellow-eyed thing scurries away just before a tall, slender alien steps out of the ship and approaches you.

>D
You sure do try to move around a lot for a dead person! The alien looks at you for a moment, then says, "Dent?" After a moment, it asks again, "Arthur Phillip Dent?"

After another moment, the alien calls you a jerk and a complete knee-biter, gets back into its ship, and disappears the same way it arrived, with a BAMF!

We are about to give you your score. Put on your peril-sensitive sunglasses now. (Hit RETURN or ENTER when ready.) >


What if?

Now, wouldn't it be nice if there was a function which stopped all pending commands (and probably turn scripts, too) from firing?

Then, we could stop all pending actions if something big happened. Like:

>N.W.E.GET LAMP.D.D
You are in front of The Super-Spreader.

You can see topless dancers here.

You can go west or south.

You go west.

You are in front of The Manhattan Restaurant of the Mind.

You can see Jake Chambers here.

Suddenly, you hear a strange noise coming from the sewer grate beneath your feet. Before you have time to register that you are looking at a pair of glowing, yellow eyes, whatever it is down there reaches up and snatches you down into the sewer!

It is pitch black.

The thing with the yellow eyes speaks. "WHAT?!?!" it groans, "IS YOUR FAVOURITE COLOUR???"

>


This is why Quest 6 does not even support concatenating commands.

And why would a player do that? It is just as much typing as doing it one command at a time.

[Sorry - that was no actual help]


And why would a player do that? It is just as much typing as doing it one command at a time.

If you're using the web player, there can be significant lag before a command is accepted. If you've already made a map of a town, and you know where you're going, it seems quite reasonable to enter a whole bunch of directions at once to get there.

"NOT A COLOUR!!!" The thing is shrieking,

I don't think that should happen. Multiple commands on a line are put into a stringlist and then iterated over. If one of them triggers a get input, it should expect input from the client as normal, not from the command list.

On the other hand, if the player is expected to enter the command "say yellow" or something, that would be a problem. As it would if the player enters a colour, only for the remainder of their queued commands to execute.

Therefore I would suggest that traps, wandering monsters, and other unexpected events should always do:

game.pov.commandqueue = null

or possibly:

JS.eval("$('#txtCommand').val() || $('#txtCommand').val('" + Replace(Replace (Join (game.pov.commandqueue, "."), "\\", "\\\\"), "'", "\\'") + "');")
game.pov.commandqueue = null

to type the remaining commands into the command bar for you, so that if the player wants to continue with their plan they can just hit enter.


And why would a player do that? It is just as much typing as doing it one command at a time.

I can't really explain why, but I do it all the time. I've done it ever since I learned it was possible back in the 1980s.

If it's Infocom, you can separate commands with . or then. So, sometimes it just feels natural.

You are in the Whack-A-Mole room.
You can see a hammer.
You can see a Mole.

>get hammer then whack mole
Taken.

Done.
The mole retreats into its hole.

When it comes to Quest, I've received quite a few emails with games-in-progress attached and a note to paste in something like "NW.N.NE.E.CLAP.NE.NE.SE.HOP.CLAP" to get to the point in the game where there is an issue.

(I guess the walkthrough feature isn't something most people know about.)


[Sorry - that was no actual help]

Oh, that's cool. Someone opining that whatever I'm doing might possibly be pointless is definitely helpful when I'm not thinking things through clearly.

I always want people to point out such things, as they are usually true and save me tons of wasted time.

:)


"NOT A COLOUR!!!" The thing is shrieking,

I don't think that should happen. Multiple commands on a line are put into astringlist and then iterated over. If one of them triggers a get input, it should expect input from the client as normal, not from the command list.

Hrmmm...

I need to test this out.

...but anytime I use get input once play has begun, my default switch case is HandleSingleCommand(result) as a way to let the player ignore the get input like they can certain show menus.

Now I wonder how these two things will work together. (Exciting!)

Also, game.pov.commandqueue = null was the first thing I tried. I've got tons of turnscripts and stuff running in the game I'm porting, and this throws multiple errors.

But pulling the command queue to paste it into the text input field with this?

JS.eval("$('#txtCommand').val() || $('#txtCommand').val('" + Replace(Replace (Join (game.pov.commandqueue, "."), "\\", "\\\\"), "'", "\\'") + "');")

That is an awesome idea!


Anyway, last night I couldn't fall asleep until I figured out how to make it work in the game I'm porting.

Here's a dumb example (as my code has all sorts of extra stuff in it which would be distracting, but this example has the same functions that handle all his stuff):

  <turnscript name="testerturnscript">
    <enabled />
    <script>
      firsttime{
        this.counter = 0
      }
      this.counter = this.counter + 1
      if (this.counter % 3 = 0) {
        msg ("Something important printed!")
        this.interrupt = true
      }
      else {
        msg("This text is not very important.")
      }
    </script>
  </turnscript>
  <function name="HandleNextCommandQueueItem"><![CDATA[
    if (GetBoolean(game.pov, "commandqueueinterrupt")) {
      // STOP THE PRESS!
    }
    else if (TypeOf(game.pov, "commandqueue") = "stringlist") {
      queuelength = ListCount(game.pov.commandqueue)
      if (queuelength > 0) {
        thiscommand = Trim(StringListItem(game.pov.commandqueue, 0))
        if (queuelength = 1) {
          game.pov.commandqueue = null
        }
        else {
          newqueue = NewStringList()
          for (i, 1, queuelength - 1) {
            list add (newqueue, StringListItem(game.pov.commandqueue, i))
          }
          game.pov.commandqueue = newqueue
        }
        if (LengthOf(thiscommand) > 0) {
          HandleSingleCommand (thiscommand)
        }
        else {
          HandleNextCommandQueueItem
        }
      }
    }
    set (game.pov, "commandqueueinterrupt", false)
  ]]></function>
  <function name="RunTurnScripts">
    if (IsGameRunning()) {
      if (game.menucallback = null) {
        foreach (turnscript, ObjectListSort(AllTurnScripts(), "name")) {
          if (GetBoolean(turnscript, "enabled")) {
            inscope = false
            if (turnscript.parent = game or turnscript.parent = null) {
              inscope = true
            }
            else {
              if (Contains(turnscript.parent, game.pov)) {
                inscope = true
              }
            }
            if (inscope) {
              turnscript.interrupt = false
              do (turnscript, "script")
              if (turnscript.interrupt) {
                //msg ("DEBUGGING MESSAGE: Stopping the press!")
                StopThePress
              }
              turnscript.interrupt = false
            }
          }
        }
      }
    }
  </function>
  <function name="StopThePress">
    game.pov.commandqueueinterrupt = true
    game.suppressturnscripts = true
  </function>

...and it doesn't mess up the save feature.

I think that uses start transaction rather than "handling" commands, but I'm not positive about that.


Thanks a bunch, now I have had to change QuestJS to allow players to do that!

In QuestJS, just call parser.abort().


Hrmmm...

I need to test this out.

OK… it seems that get input confuses the game. After asking the question, it executes the remaining queued commands, skipping over any parts that are inside an on ready. So it leaves the room with the trap in, walks around normally, but doesn't display any more room descriptions or trigger room enter scripts. Then when it finishes the queue, it expects a get input response from the player; after which the trap script finishes, followed by all the room descriptions and enter scripts from the remainder of the queued commands.

...but anytime I use get input once play has begun, my default switch case is HandleSingleCommand(result) as a way to let the player ignore the get input like they can certain show menus.

HandleSingleCommand(result) should be unaffected by any commands in the command queue. If one of the commands results in an extra command being called in this way, it will resolve before resuming the queue.

Also, game.pov.commandqueue = null was the first thing I tried. I've got tons of turnscripts and stuff running in the game I'm porting, and this throws multiple errors.

Can't reproduce. Can you show an example of a game that causes an error if you use this method? I tried making a simple game using a bunch of random turnscripts that could interrupt, and I completely failed to get it to fail. Would be interested to know the situation where it has a problem.

Also, now I tested it, that JS might be better converted to:

JS.eval("$('#txtCommand').val() || $('#txtCommand').val('" + Replace(Replace (Join (game.pov.commandqueue, ". "), "\\", "\\\\"), "'", "\\'") + "').select();")

This puts the remaining commands back in the queue, but also selects them. So if the player starts typing again in response to the trap or whatever, they will replace the queued commands with their own; but if they want to keep doing the same thing anyway, they can just hit enter.


(I worked around the get input problem now:

paused_commandqueue = game.pov.commandqueue
game.pov.commandqueue = null
get input {
  if (result = "purple") {
    msg ("Correct! You may continue!")
    game.pov.commandqueue = paused_commandqueue
    HandleNextCommandQueueItem
  }
  else if (result = "yellow") {
    msg ("A good answer, but not the best. You can continue if you still have confidence.")
    game.pov.HP = game.pov.HP / 2
    if (TypeOf (paused_commandqueue) = "stringlist")) {
      JS.eval("$('#txtCommand').val() || $('#txtCommand').val('" + Replace(Replace (Join (paused_commandqueue, ". "), "\\", "\\\\"), "'", "\\'") + "').select();")
    }
  else {
    msg ("Ooops! Something terrible happens!")
    game.pov.parent = mysterious jail cell
  }
}

Thanks a bunch, now I have had to change QuestJS to allow players to do that!

This made me laugh, but I promise I'm laughing with you.

(I learned that this was a thing I should have already known to handle in games after reading "Learning ZIL" by Steve Meretzky. Lots of good stuff in there! Most of it is already in QuestJS, in one form or another.)


it seems that get input confuses the game.

Damn and blast!

I was hoping it wouldn't.

I got distracted fooling around with the hint system and forgot to test it.


Can't reproduce. Can you show an example of a game that causes an error if you use this method?

Laughing maniacally. . .

I'm porting a game from ZIL to Quest. To do that easily (or at least to make the process more simple), I am using delegates and and have modified ResolveNextName and all kinds of other stuff.

I'm pretty sure the errors are . . .

Hrmm. . . I honestly have no clue what I've got going on that deleting game.pov.currentcommandqueue could break. All I know is it breaks it.

Once I've got the first act completed, I plan to post the code. So, you'll definitely get to see it within a week or three.

I also expect everyone will ask why I did this, and why I did that once I post this code, and I can't wait to see all the ways I could have handle things differently. (Seriously. I'm not being a smart-ass or anything.)


This puts the remaining commands back in the queue, but also selects them. So if the player starts typing again in response to the trap or whatever, they will replace the queued commands with their own; but if they want to keep doing the same thing anyway, they can just hit enter.

Hot dog!

I love it when a plan comes together!


Damn and blast!

Don't worry :) Look at the code I posted above (probably at the same time you were writing that response!)

I just edited it to show how it can handle different circumstances


Opinion: At the end of ResolveNextName, where it goes:

      if (HasScript(game.pov.currentcommandpattern, "script")) {
        // This is the bit that actually runs the commands
        do (game.pov.currentcommandpattern, "script", game.pov.currentcommandresolvedelements)
      }
      //
      //Setting game.runturnscripts to true to run turn scripts after ShowMenu , show menu, ask, or Ask.
      //This works in conjuction with FinishTurn, which has also been modified as of Quest 5.8.
      //- KV, 2018/05/25
      game.runturnscripts = true
      FinishTurn
      HandleNextCommandQueueItem
    }
  ]]></function>

it should be:

      if (HasScript(game.pov.currentcommandpattern, "script")) {
        // This is the bit that actually runs the commands
        do (game.pov.currentcommandpattern, "script", game.pov.currentcommandresolvedelements)
      }
      //
      //Setting game.runturnscripts to true to run turn scripts after ShowMenu , show menu, ask, or Ask.
      //This works in conjuction with FinishTurn, which has also been modified as of Quest 5.8.
      //- KV, 2018/05/25
      on ready {
        game.runturnscripts = true
        FinishTurn
        on ready {
          HandleNextCommandQueueItem
        }
      }
    }
  ]]></function>

in order to prevent get input in the command from screwing up either pending turnscripts, or other commands in the command queue.


At the end of ResolveNextName, where it goes [...] it should be [...] in order to prevent get input in the command from screwing up either pending turnscripts, or other commands in the command queue.

Brilliant! That's a very, very good idea!

@Pixie, how do we test that thoroughly? I think that is technically a bug fix.


Speaking of getting input, here's a small peek at a bit of what I've done to poor Quest to port easily from ZIL:

https://textadventures.co.uk/forum/quest/topic/bmaft_5vjee0zainnm6tkw/asking-yes-or-no-questions-without-get-input-or-ask-a-complete-waste-of-t


Hehehe.

Check this out.

If you just enter "TAKE" or "GET", it will trigger a script to ask you what you want to get. If you enter an object, it tries to take it. If you enter something other than an object, it handles your text as a command.

UPDATED

<!--Saved by Quest 5.8.7753.35184-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="alternate input getter">
    <gameid>400426c7-e5f8-4f10-8702-9324e15f55c6</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
    <start type="script">
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description><![CDATA[<br/>This is a white room with black curtains.]]></description>
    <firstenter type="script">
      msg ("PLEASE ENTER YOUR NAME")
      game.awaiting_reply = 1
      GetInput2
      on ready {
        TextCatcher
      }
    </firstenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="red herring">
      <inherit name="editor_object" />
      <take />
      <look>It's a herring, and it's red.</look>
    </object>
    <object name="black curtains">
      <inherit name="editor_object" />
      <inherit name="plural" />
      <scenery />
      <look>The curtains aren't important.{notfirst: Get on with game!}</look>
    </object>
  </object>
  <command name="yes_cmd">
    <pattern>yes;y;affirmative</pattern>
    <script>
      if (not HasAttribute(game, "awaiting_reply")) {
        game.awaiting_reply = 0
      }
      switch (game.awaiting_reply) {
        case (2) {
          msg ("Well, hello, {game.pname}!  I'm a computer! Nice to meet you!")
          msg ("")
          msg ("Now, let's get the story!")
          msg ("")
          ShowRoomDescription
        }
        default {
          msg ("You sure do sound positive!")
        }
      }
    </script>
  </command>
  <command name="no_cmd">
    <pattern>no;negative;n</pattern>
    <script>
      if (not HasAttribute(game, "awaiting_reply")) {
        game.awaiting_reply = 0
      }
      switch (game.awaiting_reply) {
        case (2) {
          msg ("Okay. Forget that then. The story begins. . .")
          game.pname = null
        }
        default {
          msg ("You sure do sound negative. . .")
        }
      }
    </script>
  </command>
  <command name="take_helper">
    <pattern>take;get;grab</pattern>
    <script><![CDATA[
      msg ("What do you want to " + game.pov.currentcommand + "?")
      GetInput2
      on ready {
        o = ResolveNameInternal("object", game.giresult, "object")
        if (o <> null) {
          HandleSingleCommand (game.pov.currentcommand + " " + game.giresult)
        }
        else {
          msg ("<br/>> " + game.giresult)
          HandleSingleCommand (game.giresult)
        }
      }
    ]]></script>
  </command>
  <function name="ResolveNextName"><![CDATA[
    resolvedall = false
    queuetype = TypeOf(game.pov, "currentcommandvarlistqueue")
    if (queuetype = "stringlist") {
      queuelength = ListCount(game.pov.currentcommandvarlistqueue)
      if (queuelength > 0) {
        // Pop next variable off the queue
        var = StringListItem(game.pov.currentcommandvarlistqueue, 0)
        if (queuelength = 1) {
          game.pov.currentcommandvarlistqueue = null
        }
        else {
          newqueue = NewStringList()
          for (i, 1, queuelength - 1) {
            list add (newqueue, StringListItem(game.pov.currentcommandvarlistqueue, i))
          }
          game.pov.currentcommandvarlistqueue = newqueue
        }
        // Resolve variable
        value = StringDictionaryItem(game.pov.currentcommandvarlist, var)
        if (value <> "") {
          result = null
          resolvinglist = false
          // This is to resolve issue 626
          if (StartsWith(var, "objectexit")) {
            result = ResolveName(var, value, "exit")
          }
          if (result = null) {
            if (StartsWith(var, "object")) {
              if (GetBoolean(game.pov.currentcommandpattern, "allow_all")) {
                scope = FilterByAttribute(GetScope("object", "", "object"), "scenery", false)
                game.pov.currentcommandpendingobjectscope = ListExclude(scope, FilterByAttribute(scope, "not_all", true))
                game.pov.currentcommandpendingvariable = var
                ResolveNameList (value, "object")
                resolvinglist = true
              }
              else if (HasScript(game.pov.currentcommandpattern, "multipleobjects")) {
                game.pov.currentcommandpendingobjectlist = NewObjectList()
                game.pov.currentcommandpendingvariable = var
                do (game.pov.currentcommandpattern, "multipleobjects")
                ResolveNameList (value, "object")
                resolvinglist = true
              }
              else {
                result = ResolveName(var, value, "object")
              }
            }
            else if (StartsWith(var, "exit")) {
              result = ResolveName(var, value, "exit")
            }
            else if (StartsWith(var, "text")) {
              result = StringDictionaryItem(game.pov.currentcommandvarlist, var)
            }
            else {
              error ("Unhandled command variable '" + var + "' - command variable names must begin with 'object', 'exit' or 'text'")
            }
          }
          // at this point, ResolveName has returned - either an object name, unresolved, or pending
          if (result = null) {
            if ((not resolvinglist) and LengthOf(GetString(game.pov, "currentcommandpendingvariable")) = 0) {
              UnresolvedCommand (value, var)
            }
          }
          else {
            AddToResolvedNames (var, result)
          }
        }
        else {
          ResolveNextName
        }
      }
      else {
        resolvedall = true
      }
    }
    else if (queuetype = "null") {
      resolvedall = true
    }
    else {
      error ("Invalid queue type")
    }
    if (resolvedall) {
      // All the objects have been resolved, so now we can actually do the command
      // TO DO: game.lastobjects should be game.pov.lastobjects
      game.lastobjects = game.pov.currentcommandresolvedobjects
      if (not DictionaryContains(game.pov.currentcommandresolvedelements, "multiple")) {
        dictionary add (game.pov.currentcommandresolvedelements, "multiple", false)
      }
      if (not GetBoolean(game.pov.currentcommandpattern, "isundo")) {
        if (LengthOf(game.pov.currentcommand) > 0) {
          start transaction (game.pov.currentcommand)
        }
      }
      if (not GetBoolean(game.pov.currentcommandpattern, "isoops")) {
        // TO DO: game.unresolved* should be game.pov.unresolved*
        game.unresolvedcommand = null
        game.unresolvedcommandvarlist = null
        game.unresolvedcommandkey = null
      }
      if (DictionaryContains(game.pov.currentcommandresolvedelements, "object")) {
        game.text_processor_this = ObjectDictionaryItem(game.pov.currentcommandresolvedelements, "object")
      }
      else if (DictionaryContains(game.pov.currentcommandresolvedelements, "object1")) {
        game.text_processor_this = ObjectDictionaryItem(game.pov.currentcommandresolvedelements, "object1")
      }
      if (HasScript(game.pov.currentcommandpattern, "script")) {
        // This is the bit that actually runs the commands
        do (game.pov.currentcommandpattern, "script", game.pov.currentcommandresolvedelements)
      }
      //
      // Setting game.runturnscripts to true to run turn scripts after ShowMenu , show menu, ask, or Ask.
      // This works in conjuction with FinishTurn, which has also been modified as of Quest 5.8.
      // - KV, 2018/05/25
      on ready {
        game.runturnscripts = true
        FinishTurn
        on ready {
          HandleNextCommandQueueItem
        }
      }
    }
  ]]></function>
  <function name="GetInput2">
    paused_commandqueue = game.pov.commandqueue
    game.pov.commandqueue = null
    get input {
      game.giresult = result
    }
    on ready {
      game.pov.commandqueue = paused_commandqueue
      HandleNextCommandQueueItem
    }
  </function>
  <function name="TextCatcher"><![CDATA[
    text = game.giresult
    if (not HasAttribute(game, "awaiting_reply")) {
      game.awaiting_reply = 0
    }
    switch (game.awaiting_reply) {
      case (1) {
        game.pname = text
        msg ("Would you like me to save that name (" + text + ") to my database?")
        game.awaiting_reply = 2
        if (GetObject("noreply") <> null) {
          destroy ("noreply")
        }
        SetTurnTimeoutID (1, "noreply") {
          game.awaiting_reply = 0
        }
      }
      default {
        // msg("I didn't understand your command.")
        HandleSingleCommand (text)
      }
    }
  ]]></function>
</asl>

Edit edit edit … so many silly typos in this code

If you just enter "TAKE" or "GET", it will trigger a script to ask you what you want to get. If you enter an object, it tries to take it. If you enter something other than an object, it handles your text as a command.

That's pretty neat, but… I think this will require a modified object-resolution script. Otherwise, I think you could end up with something like this:

==> put bunny in box
OK

==> take
What do you want to take?

==> it
Which "it" do you mean?

  1. Bunny
  2. Box

Unknown command: it.

==> 1
What do you want to take?

==>

(I don't remember the phrasing of all of the messages, but you see what I mean)

The problem being that the default ResolveNameInternal will return an object if you enter an object name (works fine), or return null if you entered a command (so it tries to parse the command, works fine), but if you entered something that matches multiple names, it displays a disambiguation menu and returns null. This means that your script attempts to interpret the player's input as a command, and gives an error message.

If they then choose a menu option (whether by typing the appropriate number or clicking), the menu response script will attempt to resolve any outstanding objects and then run game.pov.currentcommandpattern. So this time, it's running take_helper again, with an object parameter that it didn't ask for. Which then asks you to choose another object, even though you just chose one.

Worse would be if you entered a partial name such as "n". Because it could display a disambiguation menu, and then go north. This means that it gets as far as running HandleSingleCommandPattern, so you end up with something like:

==> take
What do you want to take?

==> ne
Which "ne" do you mean?

  1. Needle
  2. Newt
  3. Nebuchadnezzar's cigar case

You can't go that way.

==> 2

Error: undefined variable exit in expression exit.visible

Because this time, game.pov.currentcommandand game.pov.currentcommandpattern have been successfully changed to be "ne" and go respectively, but the menu hasn't been cancelled. So the response script for the disambiguation menu attempts to pass the parameter object = newt to the go command, which is expecting an exit parameter, not object, and therefore fails with an undefined variable error.

I'm working off the top of my head here, haven't actually tested it… but I'm pretty confident that this script as it stands will only work correctly in a game that doesn't allow disambiguation of object names.


A more logical approach, I think, would be checking if the input matches a command first. For example, have your helper command save the command that it was trying to execute, and enable a command with pattern #object# that pushes its parameter into the saved command.

Something like…

  <!-- This command catches a single command such as "take", and responds by enabling the 'catchall' command -->
  <command name="take_helper">
    <pattern>take;get;grab</pattern>
    <script><![CDATA[
      msg ("What do you want to " + game.pov.currentcommand + "?")
      catchall.command = game.pov.currentcommand
      RemoveObject (catchall)
    ]]></script>
  </command>

  <!-- this matches a command such as "sandwich" or "teddy bear" that is just an object name -->
  <!-- It will always have the lowest match strength of any command, as it is entirely parameters -->
  <command name="catchall">
    <pattern>#text#</pattern>
    <script>
      HandleSingleCommand (this.command + " " + text)
    </script>
  </command>

  <!-- this turnscript will disable 'catchall' again as soon as the player enters something which matches some command's pattern -->
  <turnscript name="cancel_catchall">
    <enabled />
    <script>
      if (HasObject (game.pov, "currentcommandpattern")) {
        if (not game.pov.currentcommandpattern = take_helper) {
          AddToInventory (catchall)
        }
      }
  </turnscript>

Well, I can safely say that I am scatter-brained!

:)

I forgot all about this thread.

There's good stuff here. There's a bug fix, and I need to test mrangel's code in that last post.


Log in to post a reply.

Support

Forums