IPTSCRAE SCRIPTING LESSON NINE
Make My Day - Defining Your Own Terms
Many languages have a method for creating user-defined functions and commands. The purpose of these is to create routines once, but use them many times. This is especially handy if a routine needs to be executed more than once, from different parts of the script. Iptscrae is no exception, and here are the secrets to accomplishing this.

{ <atomlist>} <symbol> DEF
A user-defined function is a routine that is called by name in your scripts. This command is used to create them. <symbol> is the name of the function. Whatever is in the <atomlist> is the code that will run when you call the function.

User defined functions cannot be executed until the client "sees" them in your script. Although they may be placed in any handler, they are most commonly found in the ON SIGNON handler. This causes the routines to be looked at and stored right when you log onto a Palace.

Debugging note: if you change the contents of a DEF, the DEF must be run again for the altered contents to be put into your client. If you have it in your SIGNON handler, just reloading your cyborg won't work - you'll need to log off and then back on to a Palace for it to be reinitialized.

The NAME of the defined function must be declared as a GLOBAL in any handler where you wish to use the function. It is a good habit to declare it right away so you don't forget. A common format is:
ON <HANDLER> {
  myUDF GLOBAL
  myVariable1 GLOBAL
  myVariable2 GLOBAL
   
  { routine 1 } trigger
  { routine 2 } trigger
}
By using a regular format for each of your handlers, and declaring your GLOBALs right away, you are less likely to miss something.

Once you have created your function, you "call" it with the following command:

<atomlist>EXEC
This command, which was mentioned in the NOTES section of Lesson 8, executes an atomlist. Remember, using the DEF function, you have given a name to an atomlist! Once you have declared the appropriate GLOBALs in your handler, you call your user-defined function in the INCHAT or OUTCHAT handler with the following syntax:

{ myUDF EXEC } CHATSTR "trigger" == IF

although it isn't limited to only these handlers!

Getting a Handle on Your Wardrobe
There is another method that you may use to "store" a routine in your cyborg. However, it is not quite as useful because it also affects the AV you are wearing. The first command you need to understand is:

<number>MACRO
This command causes the user to don the specified macro (a "macro" corresponds to an "avatar" - a group of props that are all worn at the same time).

Valid numbers for the PC client are from 0 to 57. For the Mac client they are 0 through 79. The values for the various key combinations on the PC are:
Key Combinations Values
CTRL 0 - CTRL9 0 - 9
F1 - F12 10 - 21
SHIFT-F1 - SHIFT-F12 22 - 33
CTRL-F1 - CTRL-F12 34 - 45
CTRL-SHIFT-F1 - CTRL-SHIFT-F12 46 - 57
On the Apple computers, they keys are mapped as follows:
Key Combinations Values
CMD-0 - CMD-9 0 - 9
CMD-SHIFT-0 - CMD-SHIFT-9 10 - 19
CMD-OPT-0 - CMD-OPT-9 20 - 29
CMD-OPT-SHIFT-0 - CMD-OPT-SHIFT-9 30 - 39
CMD-CTRL-0 - CMD-CTRL-9 40 - 49
CMD-CTRL-SHIFT-0 - CMD-CTRL-SHIFT-9 50 - 59
CMD-OPT-CTRL-0 - CMD-OPT-CTRL-9 60 - 69
CMD-SHIFT-OPT-CTRL-0 - CMD-SHIFT-OPT-CTRL-9 70 - 79

(Apple information is courtesy of ?Swed)

If you've looked at a basic cyborg file (the default that comes with the Palace Client), you'll see a line that says:

1 MACRO

In the ON SIGNON handler. All this does is "dress" the user in whatever AV they've saved as the CTRL-1 (or CMD-1) macro. If nothing is saved, then the user is dressed in the red happy face - which is what will happen if you execute any macro for which nothing has been assigned yet.

ON MACRO<number>
This is an event handler. Whatever code is in it will be executed when either of two things happens: a <number> MACRO command is issued, or you press the associated "macro" key. In any case, if you have a set of props (Avatar) associated with the key, you will be dressed in these BEFORE any of the code in this event handler is run.

Note: there is NO SPACE between the word "MACRO" and the number. In addition, only the numbers 0 through 9 are valid. I don't know why we can't have more, since we are allowed to save more macros. However, 0 through 9 are the only valid numbers for this event handler. You may have all 10 of them in your script at the same time, or any combination.

This is treated just like any other event handler. The syntax is:
ON MACRO4 {
  <routines/code>
}
Which would execute whatever code you've stored when you press the key combination for MACRO 4, or you say:

4 MACRO

somewhere in your script.

Timing is Everything
If you recall, in Lesson 8 we discussed the ALARMEXEC command. There is another way to delay events.

ON ALARM
This, again, is a handler. It is used to schedule periodic events, such as prop changes, or to provide a delayed response.

The trigger for ON ALARM is:

<ticks> ME SETALARM

This command is used to schedule an ALARM event in the future. Usually, you'll want a continual check so the ALARM handler will have a similar SETALARM statement in it, setting up a chain of alarms, with each alarm event triggering the next.

Whenever you go to a different room, however, the chain is cut because all ALARM events are cleared out of the buffer.

Keep in mind that is possible to overload the buffer with too many alarms, in which case the chain will break as well, and the ON ALARM routines cease working.

HOMEWORK:
1. Make a routine that monitors your position on the screen. When you are on the left side of the screen, it will put on AV on you, when you are on the right half, it will put another one on you. Have the ability to turn it on and off with the key phrases "split on" and "split off". Make sure it will work even after changing rooms.

2. Create a routine that will put on different macros and say different things when you log onto the server, depending upon what name you use. Put at least three different names, and include a default to use if none of the included names match.

CHALLENGE:
Create a routine that will automatically greet new people that come into the room. Since you may have more than one person coming into a room between ALARM events, you'll need a method of storing who is in the room, and updating it each time the alarm is called.

NOTES:
Here is a user-defined function from Foxy's cyborg:
  poldir GLOBAL
  poldis GLOBAL
  sine GLOBAL
  cosine GLOBAL
{
poldir 360 % theta360 =
theta360 theta90 =
;IF quad = 1 then nothing, IF quad = 2 then theta90 = 180-theta
;IF quad = 3 then theta90 = theta-180, IF quad = 4 then theta90 = 360-theta
  { -1 theta90 *= } theta90 270 > IF
  { 360 theta90 += } theta90 0 < IF
  { 180 theta90 -= } theta90 180 > IF
  { -1 theta90 *= } theta90 90 > IF
  { 180 theta90 += } theta90 0 < IF
; Compute cos 100 *
  poldis cos1st =
  theta90 theta90 * poldis * 2 / 3249 / cos2nd =
  theta90 theta90 * theta90 * 57 / theta90 * 24 / poldis * 188091 / cos3rd =
  cos1st cos2nd - cos3rd + cosine =
;
; Compute sin 100 *
  theta90 poldis * 57 / sin1st =
  theta90 theta90 * theta90 * 57 / poldis * 6 / 57 / 57 / sin2nd =
  theta90 theta90 * theta90 * theta90 * 120 / theta90 * 57 / poldis *
10776818
/ sin3rd =
  sin2nd sin1st - sin3rd - sine =
  { -1 sine *= } theta360 180 > IF
  { -1 cosine *= } theta360 270 < IF
  { -1 cosine *= } theta360 90 < IF
} polar DEF
Foxy obtained this amazing piece of math from TAK Lee, who runs the CyberKorea palace, took it out of the routine he had, and converted it to a DEF function. What it does is fairly simple in concept, though a bit complicated in practice. You set two variables: poldir and poldis. You get back two variables: sine and cosine. Poldir is the direction you want to go, an even number from 1 to 360. (You can specify more, if you want, but there's probably no need since that is a complete circle.) Then you set poldis to be the distance in pixels. Sine and cosine will then contain the row and column differences to add to whatever co-ordinate you have in order to be that many pixels away in the specified direction. This means you can draw circles, arcs, and other things, simply by calculating different directions with the same distance and adding the results into the center point. It creates lag when calculating, and more lag when you draw- you can only put about 127 lines on the screen at once, and a fairly large, believable circle can take all of them, creating all sorts of lag.

If it's any comfort, you're not required to totally understand and use this routine now- just save it for future reference, and remember this as an example of why you need a DEF command! (Who in their right mind would want to repeat that piece of code in every routine that used it?)

<Previous> <Iptscrae> <Next>