There is a new version of the forums ready for testing. Please post here if you're willing to help test! We could also use the help of coders!

Author Topic: TOOL: SCABS, tool & technique for scripting non-blocking NPC behaviour and more  (Read 287 times)

Hi all,

I've been developing a system for scripting non-player behaviour in AGS inspired by the way the Sierra Creative Interpreter does this.
I present to you: Switch Case Action/Behaviour System, or SCABS for short.

First, characters must have a custom property (int) SCABS which is initialised as zero.

They also have a custom property (int) delayClicker also initialised at Zero.

The SCABS function is a character extender function which returns the character's SCABS value, but can also be used to increment or change this number. (Character.SCABS(1) will increment, Character(50) sets SCABS to 50, Character.SCABS() will just return the SCABS value.)

There's another (character) custom extender function which creates a delay without using a timer, using another custom property 'delayClicker' to count game cycles without having to set a timer. It returns true when it reaches the amount of seconds you call the function with.

Also there's Character.SCABSwalk, which just moves the character to a destination and changes the SCAB value when they get there. Default value is 1, or increment, but can be set to change to any block in the switch case.

But you can use any conditions you want to check and issue the next instruction, just be aware that the switch case is running every game loop so you usually need to change the SCABS value immediately as you issue instructions.

eg Character.delay(2.5) will return true after 2.5 seconds.


In a room script make a function which will be called from room_RepExec() with a switch case like this:
Code: Adventure Game Studio
  1. function moveChar(Character* theChar) //can be used for multiple characters
  2. {
  3.   switch(theChar.SCABS())
  4.   {
  5.     case 0: //will initially listen to conditions in this block
  6.       if(theChar.Room == player.Room) //when the character enters this room
  7.       {
  8.         theChar.SCABS(1); // increments SCABS value, and listens to next block
  9.       }
  10.     break;
  11.     case 1:
  12.       //this function listens for two conditions,
  13.       //if the character hasn't reached the destination, and they're not
  14.       //moving, give character instructions to go there.
  15.       //if the character has reached the destination, increment SCABS
  16.       theChar.SCABSwalk(10, 10);
  17.     break;
  18.     case 2:
  19.       if(theChar.delay(4.0)) //after 4 seconds, run this block
  20.       {
  21.         theChar.SCABS(1);
  22.       }
  23.     break;
  24.     case 3:
  25.       theChar.SCABSwalk(10, 20);
  26.     break;
  27.     case 4:
  28.     //this block branches to two different cases, for example
  29.     //if you're using SCABS for a stealth puzzle, checking if the npc
  30.     //can 'see' the player.
  31.     //you can check basically any conditions you want in these.
  32.       if(player.x < theChar.x)//checks if player is to the left of theChar
  33.       {
  34.         theChar.SCABS(20);
  35.       } else {
  36.         theChar.SCABS(40);
  37.       }
  38.     break;
  39.   }
  40. }


« Last Edit: 12 Jun 2022, 22:30 by timid_dolphin »


  • Party Weekend
    • newwaveburritos worked on one or more games that was nominated for an AGS Award!
This looks useful!  Thanks for posting.


Note that you could also use the delay timer to make something happen regularly, like theChar.delay(10.0) will return true every ten seconds, or you could put a randomizing value in there to make something happen at odd frequencies if you wanted.

So you could have a simple function running from the room's repeatedly execute like:

Code: Adventure Game Studio
  2. float timing = 3.0;
  3. function oldJoeScratching()
  4. {
  5.   if(cOldJoe.delay(timing))
  6.   {
  7.     runScratchAnimation();  //the thing you wanted to happen
  8.     timing = IntToFloat(4 + Random(8));  // changes timing to random number between 4 and 12
  9.   }
  10. }