Difference between revisions of "Chapter 6"

From SphereWiki
Jump to: navigation, search
(Created page with ''''''(incomplete)''''' ==The LINK object== How to affect one object with another The biggest problem the early scripters had to overcome, was the lack of ability to access oth...')
 
Line 51: Line 51:
  
 
Another use for a LINKed object becomes apparent in the next chapter when we discuss the @Timer event. @Timer has no SRC, so you must find another way to access items outside of the script. LINK is just the tool for that. Read onward!
 
Another use for a LINKed object becomes apparent in the next chapter when we discuss the @Timer event. @Timer has no SRC, so you must find another way to access items outside of the script. LINK is just the tool for that. Read onward!
 +
 +
 +
==The @Timer Event==
 +
Or, how to irritate a large number of newbie Admins
 +
 +
 +
This is definitely the event that causes the most confusion in scripts, on the boards, and elsewhere. Here are some things you should remember about the @Timer event:
 +
# '''It is triggered when the TIMER property of an ITEM (not a character) reaches zero.'''
 +
# '''The TIMER property is decreased by ONE approximately every second. If you have a huge number of items, it may be more or less than a second, which leads to some problems we will see later.'''
 +
# '''It is not always connected with the decay of an item, but to have an @Timer event work properly, the item must have attr_decay set.'''
 +
# '''There is no SRC in an @Timer event.'''
 +
# '''There is a SRC in an @Timer event if you are using TRYSRC. :)'''
 +
 +
 +
Here's an example of the use of an @Timer event:
 +
 +
 +
<tt><font color="darkblue">[ITEMDEF i_timer_test]<br />
 +
ID=01828<br />
 +
NAME=Timer Test item<br />
 +
<br />
 +
ON=@Create<br />
 +
:TIMER = 1<br />
 +
:MORE = 0<br />
 +
<br />
 +
ON=@Timer<br />
 +
:TIMER = 1 // reset it for next time<br />
 +
:SAY The current MORE value is &lt;MORE&gt;.<br />
 +
:MORE = &lt;MORE&gt;+1<br />
 +
:RETURN 1  //  If you return 0, the item WILL decay!<br /></font></tt>
 +
 +
 +
The beginning of the script should not cause ANY problems for you right now. Notice that we set TIMER to 1 when the item is created. One second later, the @Timer event will fire.
 +
 +
 +
In the @Timer event, we make the item say the current value of the MORE property. It also sets the TIMER back to one, meaning that one second later, @Timer will execute again. This will continue until you either manually set TIMER to -1, or you destroy the item.
 +
 +
 +
Here is an example of code that will not work:
 +
 +
 +
<tt><font color="darkblue">[ITEMDEF i_timer_test]<br />
 +
ID=01828<br />
 +
NAME=Timer Test item<br />
 +
<br />
 +
ON=@Create<br />
 +
:TIMER = 1<br />
 +
:MORE = 0<br />
 +
<br />
 +
ON=@Timer<br />
 +
:TIMER = 1 // reset it for next time<br />
 +
:SRC.SAY The current MORE value is &lt;MORE&gt;.<br />
 +
:MORE = &lt;MORE&gt;+1<br />
 +
:RETURN 1  //  If you return 0, the item WILL decay!<br /></font></tt>
 +
 +
 +
You will get an error with this script. There is no SRC object in an @Timer script. None. Don't ever ever use it. I will severely berate you on the scripting boards if I see it. Then I will tell you to read this page.
 +
 +
 +
So what can you do with timers?  Well you can do any number of things.  Here is an example of a useful tool using @Timer:
 +
 +
 +
<tt><font color="darkblue">[ITEMDEF i_cool_stick]<br />
 +
ID=i_staff_black<br />
 +
NAME=cool stick<br />
 +
<br />
 +
ON=@DClick<br />
 +
:IF !(&lt;SRC.TAG0.COOLSTICK&gt;)<br />
 +
::SRC.SYSMESSAGE You have used the cool stick. You must wait ten seconds before using it again.<br />
 +
::TIMER = 10<br />
 +
::SRC.TAG.COOLSTICK = 1<br />
 +
::LINK = &lt;SRC.UID&gt;<br />
 +
:ELSE<br />
 +
::SRC.SYSMESSAGE You cannot use the cool stick right now!<br />
 +
:ENDIF<br />
 +
:RETURN 1<br />
 +
<br />
 +
ON=@Timer<br />
 +
:// Uh oh!  What do we do now?  We have no way to refer to the player!<br />
 +
:// But look!  We set the LINK of the item to the player's uid.<br />
 +
:LINK.TAG.COOLSTICK = 0<br />
 +
:TIMER = -1<br />
 +
:RETURN 1<br /></font></tt>
 +
 +
 +
What does this script do? It is a cool stick, which doesn't allow you to use it for 10 seconds after you use it the first time. It's a relatively useless item as it stands, but you might want the stick to do something, like a very powerful magic effect, or restoring mana, and then restrict its use for a while. We will see another way to do this in another section that is easier to understand. It also uses @Timer.
 +
 +
So let's break the script down. The entire middle section needs some commenting, so I shall cut and paste it here and add comments. It's easier than taking it line by line.
 +
 +
 +
<tt><font color="darkblue">ON=@DClick<br />
 +
// We set the player's TAG.COOLSTICK to 1 when they use the stick the first time.<br />
 +
// If you don't put that 0 in there, console errors will occur sometimes ("Undefined symbol ")<br />
 +
// We're testing here if the TAG.COOLSTICK is set.  Remember, an IF statement only must become true or false.<br />
 +
// Notice that we have this:  !(0&lt;SRC.TAG.COOLSTICK&gt;).  In an IF statement, ! means not, so we're testing<br />
 +
// the opposite of what it actually is.  So if it's false, it's true, and vice versa.<br />
 +
:IF !(&lt;SRC.TAG0.COOLSTICK&gt;)<br />
 +
::SRC.SYSMESSAGE You have used the cool stick.  You must wait ten seconds before using it again.<br />
 +
::// Set the TIMER to 10, for a 10 second pause.<br />
 +
::TIMER = 10<br />
 +
::SRC.TAG.COOLSTICK=1<br />
 +
::// Set the LINK on the item to the UID of the SRC.<br />
 +
::LINK = &lt;SRC.UID&gt;<br />
 +
:ELSE  // SRC.TAG.COOLSTICK was not zero<br />
 +
::SRC.SYSMESSAGE You cannot use the cool stick right now!<br />
 +
:ENDIF<br />
 +
:RETURN 1<br /></font></tt>
 +
 +
 +
I did an interesting thing there that you may not have picked up on. It is ALWAYS good scripting practice to indent the contents of a code block, particularly in complex scripts where it can be difficult to keep track of what is going on. Like so:
 +
 +
 +
<tt><font color="darkblue">IF &lt;blah&gt;<br/ >
 +
. . . indent these lines<br/ >
 +
ELSE<br/ >
 +
. . . indent these lines<br/ >
 +
. . . IF &lt;blah&gt;<br/ >
 +
. . . . . . indent these lines further<br/ >
 +
. . . ENDIF<br/ >
 +
ENDIF<br/ ></font></tt>
 +
 +
 +
It makes it much easier to read. It also makes it easier to see if you have the same number of IFs and ENDIFs, which is always useful. Some text editors will automatically do the indenting for you.
 +
 +
 +
Now, the @Timer script on this item accesses the player through the LINK object. It resets the player's TAG.COOLSTICK to zero.  The next time the player double-clicks on the cool stick, it will recognize that, and the player will use the cool stick again.
 +
 +
 +
===TRYSRC===
 +
There is one very hot thing about timers. It is TRYSRC. The correct syntax is: TRYSRC &lt;uid_of_something_what_you_want_to_become_src&gt; <function_or_command>. TRYSRC allows you to change SRC for that line only. So to contradict the above rules:
 +
 +
 +
There is an SRC in an @Timer event if you are using '''TRYSRC''' :)
 +
 +
 +
For example:
 +
 +
 +
<tt><font color="darkblue">ON=@Timer<br />
 +
:// display a message over the LINK object that can be seen by TOPOBJ (TOPOBJ is a reference to the top-most<br />
 +
:// object that contains this object, for example the character that has the item equipped)<br />
 +
:TRYSRC <TOPOBJ.UID> LINK.MESSAGE Hello There! // if you recall, the MESSAGE function only shows a message to SRC<br />
 +
:RETURN 1<br /></font></tt>
 +
 +
 +
And another:
 +
 +
 +
<tt><font color="darkblue">ON=@Timer<br />
 +
:// place 5000 gold coins in LINK's backpack<br />
 +
:SERV.NEWITEM i_gold<br />
 +
:NEW.AMOUNT = 5000<br />
 +
:TRYSRC <LINK.UID> NEW.BOUNCE // the BOUNCE function places an item into SRC's backpack<br />
 +
:RETURN 1<br /></font></tt>
 +
 +
 +
That's about all you need to know about @Timer events. Later on we will move on to another confusing set of events.

Revision as of 16:10, 1 June 2009

(incomplete)

The LINK object

How to affect one object with another


The biggest problem the early scripters had to overcome, was the lack of ability to access other objects via a script. The only two objects possible to access were the SRC and the default object. And the LINK. The LINK made it possible to do things in version .40 that most people don't suspect are possible even in SPHERE .55i.


The LINK property of an item holds the UID of another object. Then, it serves as an object reference to directly access that object. The LINK property can be set in-game or in a script. Here's an example:


[ITEMDEF i_link_test]
ID=01828
NAME=Link Test

ON=@DClick

MESSAGE The LINK's name is <LINK.NAME>.
RETURN 1


Now, create this item in-game and set its LINK to the UID of another object. (Use the .info command or .xshow uid to get the UID.) Double-click the Link Test item. It will say the name of the object you linked it to. This obviously has very little use, so here I offer you a piece of a script I wrote a while ago that uses the LINK object. (The items have been changed to protect the innocent.)


[ITEMDEF i_tile_sender]
ID=01828
NAME=Sender tile

ON=@DClick

IF (!<LINK.UID>) // If there is no link yet
TARGET Select an object to link to.
RETURN 1
ELSE
LINK.SAY <SRC.NAME> is knocking at your door!
RETURN 1
ENDIF


ON=@TargOn_Item

LINK = <SRC.TARG.UID> // Put the UID of the targeted item into LINK
RETURN 1


ON=@TargOn_Char

LINK = <SRC.TARG.UID> // Put the UID of the targeted character into LINK
RETURN 1


This script has no real apparent use either, but put the item in front of a house, and let the house owner link it to an item of his choosing. (He would probably want to link it to his backpack because he'll have that with him all the time. He might even want to link it to himself.) When someone comes to his house, they can double-click the tile, and the house owner will get a "Knock knock" style message so he can go see what's happening at his house.


Do you understand the script? You should understand the part dealing with the IF statement, and the TARGET function. If you don't, reread the script until you do, or the earlier chapters dealing with those particular aspects of scripting. The only part here that's new is the LINK.SAY function, which causes the LINKed item to SAY whatever the scripter wants.


Another use for a LINKed object becomes apparent in the next chapter when we discuss the @Timer event. @Timer has no SRC, so you must find another way to access items outside of the script. LINK is just the tool for that. Read onward!


The @Timer Event

Or, how to irritate a large number of newbie Admins


This is definitely the event that causes the most confusion in scripts, on the boards, and elsewhere. Here are some things you should remember about the @Timer event:

  1. It is triggered when the TIMER property of an ITEM (not a character) reaches zero.
  2. The TIMER property is decreased by ONE approximately every second. If you have a huge number of items, it may be more or less than a second, which leads to some problems we will see later.
  3. It is not always connected with the decay of an item, but to have an @Timer event work properly, the item must have attr_decay set.
  4. There is no SRC in an @Timer event.
  5. There is a SRC in an @Timer event if you are using TRYSRC. :)


Here's an example of the use of an @Timer event:


[ITEMDEF i_timer_test]
ID=01828
NAME=Timer Test item

ON=@Create

TIMER = 1
MORE = 0


ON=@Timer

TIMER = 1 // reset it for next time
SAY The current MORE value is <MORE>.
MORE = <MORE>+1
RETURN 1 // If you return 0, the item WILL decay!


The beginning of the script should not cause ANY problems for you right now. Notice that we set TIMER to 1 when the item is created. One second later, the @Timer event will fire.


In the @Timer event, we make the item say the current value of the MORE property. It also sets the TIMER back to one, meaning that one second later, @Timer will execute again. This will continue until you either manually set TIMER to -1, or you destroy the item.


Here is an example of code that will not work:


[ITEMDEF i_timer_test]
ID=01828
NAME=Timer Test item

ON=@Create

TIMER = 1
MORE = 0


ON=@Timer

TIMER = 1 // reset it for next time
SRC.SAY The current MORE value is <MORE>.
MORE = <MORE>+1
RETURN 1 // If you return 0, the item WILL decay!


You will get an error with this script. There is no SRC object in an @Timer script. None. Don't ever ever use it. I will severely berate you on the scripting boards if I see it. Then I will tell you to read this page.


So what can you do with timers? Well you can do any number of things. Here is an example of a useful tool using @Timer:


[ITEMDEF i_cool_stick]
ID=i_staff_black
NAME=cool stick

ON=@DClick

IF !(<SRC.TAG0.COOLSTICK>)
SRC.SYSMESSAGE You have used the cool stick. You must wait ten seconds before using it again.
TIMER = 10
SRC.TAG.COOLSTICK = 1
LINK = <SRC.UID>
ELSE
SRC.SYSMESSAGE You cannot use the cool stick right now!
ENDIF
RETURN 1


ON=@Timer

// Uh oh! What do we do now? We have no way to refer to the player!
// But look! We set the LINK of the item to the player's uid.
LINK.TAG.COOLSTICK = 0
TIMER = -1
RETURN 1


What does this script do? It is a cool stick, which doesn't allow you to use it for 10 seconds after you use it the first time. It's a relatively useless item as it stands, but you might want the stick to do something, like a very powerful magic effect, or restoring mana, and then restrict its use for a while. We will see another way to do this in another section that is easier to understand. It also uses @Timer.

So let's break the script down. The entire middle section needs some commenting, so I shall cut and paste it here and add comments. It's easier than taking it line by line.


ON=@DClick
// We set the player's TAG.COOLSTICK to 1 when they use the stick the first time.
// If you don't put that 0 in there, console errors will occur sometimes ("Undefined symbol ")
// We're testing here if the TAG.COOLSTICK is set. Remember, an IF statement only must become true or false.
// Notice that we have this:  !(0<SRC.TAG.COOLSTICK>). In an IF statement, ! means not, so we're testing
// the opposite of what it actually is. So if it's false, it's true, and vice versa.

IF !(<SRC.TAG0.COOLSTICK>)
SRC.SYSMESSAGE You have used the cool stick. You must wait ten seconds before using it again.
// Set the TIMER to 10, for a 10 second pause.
TIMER = 10
SRC.TAG.COOLSTICK=1
// Set the LINK on the item to the UID of the SRC.
LINK = <SRC.UID>
ELSE // SRC.TAG.COOLSTICK was not zero
SRC.SYSMESSAGE You cannot use the cool stick right now!
ENDIF
RETURN 1


I did an interesting thing there that you may not have picked up on. It is ALWAYS good scripting practice to indent the contents of a code block, particularly in complex scripts where it can be difficult to keep track of what is going on. Like so:


IF <blah>
. . . indent these lines
ELSE
. . . indent these lines
. . . IF <blah>
. . . . . . indent these lines further
. . . ENDIF
ENDIF


It makes it much easier to read. It also makes it easier to see if you have the same number of IFs and ENDIFs, which is always useful. Some text editors will automatically do the indenting for you.


Now, the @Timer script on this item accesses the player through the LINK object. It resets the player's TAG.COOLSTICK to zero. The next time the player double-clicks on the cool stick, it will recognize that, and the player will use the cool stick again.


TRYSRC

There is one very hot thing about timers. It is TRYSRC. The correct syntax is: TRYSRC <uid_of_something_what_you_want_to_become_src> <function_or_command>. TRYSRC allows you to change SRC for that line only. So to contradict the above rules:


There is an SRC in an @Timer event if you are using TRYSRC :)


For example:


ON=@Timer

// display a message over the LINK object that can be seen by TOPOBJ (TOPOBJ is a reference to the top-most
// object that contains this object, for example the character that has the item equipped)
TRYSRC <TOPOBJ.UID> LINK.MESSAGE Hello There! // if you recall, the MESSAGE function only shows a message to SRC
RETURN 1


And another:


ON=@Timer

// place 5000 gold coins in LINK's backpack
SERV.NEWITEM i_gold
NEW.AMOUNT = 5000
TRYSRC <LINK.UID> NEW.BOUNCE // the BOUNCE function places an item into SRC's backpack
RETURN 1


That's about all you need to know about @Timer events. Later on we will move on to another confusing set of events.