https://www.ultima-strike.com/dokuman/doc-uo-sphere
https://sphere.uozone.net/index.php?title=Main_Page
How to make decisions in a script
It was an amazing day when someone showed this script to me. This was actually the script that tested the "new" scripting system in version .37. SPHERE wasn't even SPHERE then. It was called "Grayworld" and was on menasoft.com. Actually, I believe it was in the Admin FAQ that they used to have on the website. Here it is, updated to 55i format:
[TYPEDEF T_VEND_MACHINE]
// Some other trigger.
// Vending machine.
ON=@DCLICK
IF <SRC.RESTEST 10 i_gold>
SERV.NEWITEM={ i_HAM 1 i_fruit_apple 1 i_bread_loaf 1 i_bacon_slice 1 i_RIBS_COOKED 1 i_SAUSAGES 1}
SRC.BOUNCE <NEW.UID> // put it in your pack.
SRC.CONSUME 10 i_gold
SRC.MESSAGE That will be 10 Gold Thank Thee.
SOUND 0F7
ELSE
MESSAGE You lack 10 Gold to pay.
ENDIF
RETURN 1
Put this script into one of your files and resync your server. I like to use spheretrig.scp for test triggers like this. Now, in the game, type .set type t_vend_machine and target any item (like a door). Then double-click it and watch what happens. If you get the "not enough gold" message, .add yourself some i_gold, and try again.
See the result of this simple little script? It's got a lot that we've dicussed, and even more that we haven't. First, you may notice the use of this strange IF construction. You will use this again and again, so pay attention! The IF structure looks like this:
IF (1 or 0)
// Execute these lines if 1
ELIF (1 or 0)
// Execute these lines if the first wasn't 1, but this one is
// You can have as many ELIFs as you need
ELSE
// Execute if none of the above are 1
ENDIF
Always, always, always, always pair your IF with an ENDIF. It doesn't matter what's in the middle. You can have eight hundred ELIFs and an ELSE. But ALWAYS be sure your IF is paired somewhere with an ENDIF. Actually those are the only two required parts of this construction. ELSE and ELIF are completely optional, and you should only use them if they are absolutely needed.
So what is this "1 or 0" thing? How does it help me in my scripting if I'm just typing a 1 or a 0 in there? Actually, you will NEVER type a 1 or a 0 in there, and this is a perfect time to introduce the equivalence test operators. Here they are:
== equal to
!= not equal to
> greater than
< less than
<= less than or equal to
>= greater than or equal to
1 = true
0 = false
I've put this table in bold since it's so incredibly important. And here is another SPHERE principle:
Do not use == and = interchangably in an IF statement. SPHERE actually allows this, but you will get confused and use == where you mean =, and vice versa.
Here is an example of using a equivalence operator in an IF statement:
IF (<SRC.STR>==75)
Read this "If src.str is equal to 75". Want to know something interesting? Internally, if SRC.STR is in fact equal to 75, SPHERE will replace the ENTIRE part inside the parentheses with a 1. If it is not equal to 75, SPHERE will replace that part with a 0. That's where your 1 and 0 comes from.
Now you may be wondering, what the < > brackets around <SRC.STR> are doing there. Actually, this is one of the most elusive concepts in SPHERE scripting. The < > brackets mean "Replace whatever is inside with the actual value of that thing." This is done before any testing is executed. Say SRC.STR has been set to 71. Here are the steps SPHERE takes in simplifying this IF statement:
IF (<SRC.STR>==75)
IF (71 == 75)
IF (0)
Notice above in the example script that we have this statement:
<SRC.RESTEST 10 i_gold>
"What the heck is RESTEST?" RESTEST is what we call a function. It takes parameters (in this case an amount and an item ID) and returns a value. SPHERE replaces the entire function statement <SRC.RESTEST 10 i_gold> with that value. RESTEST checks to see if the player has an amount of the item specified greater than the amount specified:
"Does the player have an amount of i_gold equal to or greater than 10?" is what the function asks. Internally SPHERE says "Yes" and replaces it with a 1, or "No" and replaces it with a 0.
Say the player had 9 gold in his backpack. Here is the simplification of the IF statement:
IF (<SRC.RESTEST 10 i_gold>)
IF (0)
We'll see in later chapters how to define our own functions, give them parameters and have them return a value!
I hope you have a general understanding of the IF statement now. Here is a more complex example for you to analyze:
IF (<SRC.STR>>60)
SRC.SYSMESSAGE Your strength is greater than 60.
ELIF (<SRC.STR>>40)
SRC.SYSMESSAGE Your strength is greater than 40, but less than 60.
ELIF (<SRC.STR>>20)
SRC.SYSMESSAGE You are a weakling with between 20 and 40 strength.
ELSE
SRC.SYSMESSAGE Start lifting weights because your strength is less than 20!
ENDIF
What does this do? Well first, SPHERE looks at the IF statement, and says "Is the value of SRC.STR greater than 60?" If the answer is no, SPHERE replaces that with a 0, and jumps down to the first ELIF. "Is the value of SRC.STR greater than 40?" If not, it jumps down to the next one. "Is the value of SRC.STR greater than 20?" If not, it looks for further ELIFs. Unable to find them, it jumps to the ELSE statement, since nothing above was true.
SYSMESSAGE prints out a message to the corner of the screen of the referenced object. In this case, that's SRC. Earlier, you saw an example involving the MESSAGE function. It prints the message above the object referenced. If the object is inside of a closer container, it does a SYSMESSAGE to the topmost container object. This means that if an item in a backpack is given a MESSAGE command, and the backpack is not opened, the player will see the message in the corner of his screen.
SYSMESSAGE [text]
MESSAGE [text]
RESTEST [amount] [item]
NEWITEM [item]
BOUNCE // Put an item into the character's backpack
Your first five functions. Congratuations. Actually, you saw another one in an earlier script! Remember what it is?
SAY [text]
This, of course, causes the object to SAY (so everyone can hear it) the text given. With MESSAGE and SYSMESSAGE, the text is private to a single client. MESSAGE text is only visible to the SRC. (In other words, LINK.MESSAGE or SRC.TARG.MESSAGE does nothing, which is something they really need to fix!)
So finally, what is this weird RETURN 1 at the end of the script?
RETURN is used in a variety of ways. In the case of an event script, if you RETURN 1, it prevents the default action from happening. For example, if you put this on an item in the game and double-click it, it doesn't actually try to use the item too. It just executes the double-click script. (To a player it would look like he was using the item, but we know better.) If you change it to RETURN 0, it would try to use the item too, realize it had no idea what to do with this item, and say "You are not sure how to use this item" or something like that. Either way, the script ends as soon as it sees a RETURN statement. The distinction between RETURN 1 and RETURN 0 is even more clear in character events, and I shall make an effort to point that out at the time.