Magine: so, any questions from last time?
ZebLith: No questions. :)
Magine: ok
Magine: so does this class seem to be making things more clear at all?
:D
ZebLith: In many areas, yes. :)
Magine: have you taken a look at the standard behavior table, btw?
ZebLith: Standard behaviour table meaning the behaviour table I have
set up (alt+b) or a "default"?
Magine: the table that comes in the .zip
Magine: did you set one up of your own?
ZebLith: Not really, I played around with a few commands but never
saved them. So it basically is the one from the zip file.
Magine: yes
Magine: i thought today i would just go thru some parts of the table
and try to clarify them
Magine: if that's possible, heheh
ZebLith: heh well let's see ^^
Magine: just trying to decide what part to start with....
Magine: any section that interests you in particular?
ZebLith: Hmm...nothing in particular....
Magine: well, let's start at the top.....
Magine: alt-B to open it (saying that for the benefit of log readers)
Magine: the first section handles recording...but that's a bit complicated
to start with, so let's move down to the survey/build section
Magine: the first row after the comment is event=any, action=check
1
Magine: all that does is let you "turn off" that section of the table
if you aren't going to use it
Magine: if you wanted to deactivate that section, you would change
"check 1" to "check 0"
ZebLith: ah okay
Magine: all the check command does is turn row-by-row checking on or
off
Magine: check 0 turns it off and check 1 turns it back on, of course
Magine: when checking is turned off, then only rows with the ANY event
will be examined
Magine: until the next "check 1" occurs
Magine: this is somewhat similar to the ENDCHECK command, which tells
the program to stop checking rows entirely
Magine: well, stop checking rows that match the particular event
Magine: hm, let me try to explain that better...
Magine: when an event occurs, it is sent to the behavior table, as
we talked about before,
Magine: but only rows whose event column has that particular event
are actually examined
Magine: so for instance during a "HEAR" event,
Magine: only rows with event=hear (or event=any) will be looked at.
Magine: rows with other events will be skipped over entirely.
Magine: make sense? :)
ZebLith: perfect sense. :)
Magine: ok, so the next row of the survey/build section, following
ANY/CHECK 1, has Event=STARTUP
Magine: this is an event that's internal to magsbot, unlike most events
which represent messages from the world server.
Magine: any rows of the behavior table that have event=startup will
be checked when the program begins
Magine: (unless checking is turned off for a row due to a previous
row having CHECK 0 or ENDCHECK)
Magine: so, in this case, the STARTUP row is just initializing some
global variables.
Magine: initializing means giving them some value to begin with, of
course....and we talked about global variables before
ZebLith: right and yes. :)
Magine: so the variables we see here, @clicklog, @selllog, @surveylog
and $logger are all global variables that are used by the build/survey
section of the behaior table.
Magine: there are several kinds of survey that can be done using the
buttons on the action panel,
Magine: and those global variables are used to specify which kind of
survey.
Magine: when you click a survey button on the actions panel, some of
those variables are given a value of 1, depending on the kind of survey
operation you're doing.
Magine: so, on the next row,
Magine: we see event OBJECTCLICK
Magine: followed by an expression @gv_[clicklog]&&@eq[$avname,$gv_[logger]]
Magine: the first part of that, @gv_[clicklog], just gets the value
of global variable @clicklog
Magine: and the second part,
Magine: compares $avname (which as you recall is a macro for $atr[avatar_name],
which in turn indicates the name of the avatar responsible for the event)
...with the global variable $logger.
ZebLith: and $logger would be the person you select for magsbot to
recognize to do the clicking for object logging, right?
Magine: correct
Magine: let me clarify some things here :)
Magine: when you click the "Log Objects by Click" button on the actions
panel,
Magine: it creates a pop-up dialog that lets you choose an avatar from
the list of nearby avs,
Magine: and assigns that name to $logger
Magine: so you can see here that if someone clicks on an object,
Magine: the OBJECTCLICK event will occur and be sent to the bot, which
in turn sends that to the behavior table,
Magine: and when the row we're looking at is checked,
Magine: the action will only be triggered if
Magine: the @clicklog global variable is "true" (1) ...which
it will be if you clicked the "log objects by click" button earlier
Magine: and the name of the avatar who clicked on the object equals
that name that was assigned in the "log objects by click" button
Magine: so knowing all that, does the expression there make sense to
you? :)
ZebLith: perfectly. ^^
Magine: ok :) ...two other things i'll mention about the expression,
Magine: first, the @eq function there
Magine: is used because as you will recall, in magsbot's language you
can't compare strings directly
Magine: so you could not say $logger=$avname, for example
Magine: instead you say @eq[$logger,$avname]
Magine: ...and the second thing about the expression that i should
mention is this:
Magine: you may wonder why i use the @gv_ function instead of just
putting
Magine: OBJECTCLICK @clicklog && @eq[$logger,$avname]
Magine: do you want to take a guess? :)
ZebLith: My guess would be that you want it to look at the global variables
first and that there may be a local variable of the same name you want
it to ignore.
Magine: well, that's a good guess, but no :D
ZebLith: lol so it is there to...? ^^
Magine: you don't need to do that because at this point, in the event,
there aren't going to be any local variables yet
Magine: (unless you created them in the expression itself)
Magine: so you know $logger and @clicklog must refer to globals
Magine: but the reason you use @gv_ and $gv_ instead of referring to
them directly,
Magine: is because you aren't sure if those variables exist at all!
Magine: if someone hasn't used the "log objects by click" button, then
there may not be any variables named $logger or @clicklog
Magine: (well actually, that's sort of untrue....you know that there
are because they were created in the STARTUP event above)
Magine: (but if it wasn't for that STARTUP event, you wouldn't know
if those variables existed or not)
Magine: (actually i should get rid of the STARTUP there, it was put
there in an earlier version, but it's not really needed now because the
@gv_ and $gv_ are being used)
Magine: anyway, the point is...
ZebLith: well in my behaviour table, it's just @clicklog, not @gv_[clicklog]
Magine: ah ok :)
Magine: you must have an older table
Magine: that's why i put the STARTUP event there originally,
Magine: to make sure that @clicklog and $logger exist
Magine: because if you refer directly to a variable that doesn't exist,
you get an error message
Magine: but in more recent versions of magsbot,
Magine: i try to use the @gv_ and $gv_ functions to refer to globals
in the behavior table
Magine: because the @gv_ and $gv_ will NOT cause an error if the variable
doesn't exist
Magine: instead the @gv_ will return 0 and the $gv_ will return an
empty string "" if the variables don't exist.
Magine: of course i could change magsbot so it doesn't give an error
when you directly refer to nonexistant variables,
Magine: but sometimes it's a good thing to give an error, so the user
will know that something is wrong.
Magine: so anyway...the point is, that you would use @gv_[x] instead
of just @x if you aren't sure @x exists and don't want to get an error
message
Magine: or you would use $gv_[x] instead of $x, the same way, the avoid
an error message when unsure if $x exists.
Magine: so does that make sense? :)
ZebLith: yes :) (And as to my previous thought, doesn't it refer
to globals first anyways? >_<)
Magine: nope, just the opposite
Magine: when magsbot sees a variable like @x
Magine: it FIRST looks to see if there is a local variable with that
name
Magine: and if it doesn't exist, then it looks for a global of that
name.
ZebLith: okay, I don't know why I thought that, lol okay, gotcha.
Magine: ok...so now for the Action on that same row of the table...
Magine: first there is just a comment, a REMark statement:
Magine: REM log clicked object;
Magine: then there is the command CLICKBTN "Survey/[LogObject]",
Magine: which causes the button "[LogObject]" on the Survey tab of
the actions panel to be activated
[which causes the information for the object to be put into the list
named ObjLog...more on that in a moment]
Magine: and finally the command WHISPER $logger $gv_[$fmt["objlog:%s",@objnum]]
Magine: which causes a formatted message to be whispered to the person
who clicked on the object.
Magine: (within the action we don't need to use $gv_[logger] because
the action will never occur unless $logger exists.)
Magine: but what is that other stuff there? :D the $gv_[$fmt["objlog:%s",@objnum]]
looks rather confusing, huh? :D
ZebLith: oh yes very! lol
Magine: well first let's just look at the inner part, $fmt["objlog:%s",@objnum]
Magine: the $fmt function is a string formatting function
Magine: similar to printf in C, by the way :)
ZebLith: ah :)
Magine: the first parameter ("argument") that we give the $fmt function
is a format string
Magine: and the following arguments, of which there can be up to 11,
[twelve arguments max for a magsbot function]
Magine: specifies the values that we want to insert into the format
string.
Magine: in other words,
Magine: whereever there is a %s in the format string,
Magine: the $fmt function will insert one of the values from the rest
of the arguments
Magine: so $fmt["objlog:%s",@objnum] will take the value of @objnum
and insert it into "objlog:%s" where the %s is.
Magine: so if @objnum was 12345 then $fmt["objlog:%s",@objnum] would
return "objlog:12345"
Magine: make sense? :)
ZebLith: yeah :)
Magine: i'll comment here for the benefit of log readers who might
know some C,
Magine: that unlike the C sprint function that has other specifiers
besides %s
Magine: in magsbot you always use %s because all magsbot variables
are "variant" type
Magine: (if you don't know what all that means, don't worry, you don't
need to, heheh)
Magine: (i only mentioned this so any C users won't [get confused trying
to use] %d or other specifiers besides %s like you do in C)
ZebLith: okay, a question on $fmt for a second?
Magine: sure, what?
ZebLith: lets say for example...$fmt["objlog:%s %s",@objnum,@objnumX]
would it print @objnum first THEN @objnumX? or @objnumX then @objnum?
Magine: if @objnum was 123 and @objnumX was 456,
Magine: then $fmt["objlog:%s %s",@objnum,@objnumX] would give
you
Magine: "objlog:123 456"
Magine: @objnum comes first in your list, so it gets inserted first.
ZebLith: okay! great :)
Magine: ok....so now we know what that $fmt function in the OBJECTCLICK
row means, sort of :D
ZebLith: ^^
Magine: the $fmt["objlog:%s",@objnum] will create a string like "objlog:12345"
using the value of @objnum
Magine: but what is @objnum? :D
Magine: well, it's another macro like $avname
Magine: it's a convenient abbreviation for @atr[object_number]
Magine: which in this case refers to the object number of the object
that was clicked on
Magine: so what is happening here, is this....
Magine: when someone clicks an object, there is an objectclick event,
Magine: and if the person doing the clicking is the $logger
Magine: (if their name = the value stored in global variable $logger)
Magine: and if the @clicklog global is 1 (meaning that logging objects
by click has been turned on)
Magine: then the [LogObject] button in the survey category of the action
panel will be clicked
Magine: (which, though I didn't say so before, will create an item
in a list named ObjLog, with a name like $objlog:12345)
Magine: and then the bot will whisper the value of that list item to
the person who clicked the object.
Magine: of course to really understand this you also need to know what
the [LogObject] button is doing
Magine: and next time we'll look at some button code,
Magine: but for now all you need to know is what the [LogObject] button
does
Magine: which is, as i said, to create an item in the string list named
ObjLog.
Magine: the item will have a name like $objlog:12345, where 12345 is
the object number
Magine: and the value stored in $objlog:12345 will be a string
containing information about the object clicked.
Magine: (that's what [LogObject] does...it creates that string with
info about the object, and puts the string into the ObjLog list)
Magine: i hope that makes some kind of sense :D
ZebLith: heheh :)
Magine: actually the process was much more complicated before the [more
recent versions of the sdk]
Magine: because in earlier versions you only got the object number
when you clicked an object,
Magine: you didn't get any other information about the object when
clicking it,
Magine: so the "log objects by click" routine had to also do a survey
afterward in order to get the object information.
ZebLith: aah
Magine: but now that you get all the object info when you click an
object, it's much simpler.
Magine: you just take the info when the person clicks the object, and
put it directly into ObjLog
Magine: so is it becoming clear?
ZebLith: *nods*
Magine: no questions? :)
ZebLith: None right now :)
Magine: ok
Magine: well, the next row of the behavior table, which has Event=OBJECTSELECT
@gv_[sellog]&&@eq[$avname,$gv_[logger]]
Magine: does much the same thing as the row above,
Magine: the only difference is,
Magine: instead of logging objects that are clicked on,
Magine: it logs objects that are *selected*
Magine: the @sellog global is like the @clicklog global....@sellog
gets assigned a value of 1 when someone clicks the "Log Objects by Select"
button
Magine: otherwise it's all the same.
Magine: ok, so....the row after that one, has Event=CELLOBJECT @gv_[surveylog]
Magine: now that row also does something similar...it also puts object
information into the ObjLog list
Magine: but instead of doing that when someone clicks on an object
or selects an object,
Magine: it does it when an CELLOBJECT event occurs....which means,
during a survey.
Magine: that's how a survey works, in fact: the bot gets a lot of CELLOBJECT
messages,
Magine: each containing information about one object in the survey.
Magine: so...when a user clicks the "Log from Survey" button on the
actions panel,
Magine: it assigns 1 to @surveylog, and starts a survey going.
Magine: then during the survey,
Magine: the behavior table receives numerous CELLOBJECT messages
Magine: and since @surveylog=1, that row of the behavior table responds
to each CELLOBJECT message,
Magine: by putting the object info into the ObjLog list.
Magine: the same as the rows above put object info into the ObjLog
list when a user clicks an object or selects an object.
Magine: does that make sense? :)
ZebLith: yes :D
Magine: the one additional complication here, you will notice if you
look in the action column for this row,
Magine: is that a different function is used to store the information
in the list,
Magine: depending on the value of the global @relsurv.
Magine: you can see by looking at the code in the action column,
Magine: it says
Magine: IF @gv_[relsurv] { CLICKBTN "Survey/[LogObj]" }ELSE { CLICKBTN
"Survey/[LogObject]" }
Magine: so, if @relsurv is 1, then the [LogObj] button is used,
Magine: or if @relsurv is 0, then the [LogObject] button is used ObjLog
instead.
[both [LogObj] and [LogObject] put object information into the ObjLog list,]
Magine: the only difference between the [LogObj] and [LogObject] buttons
is,
Magine: that [LogObject] puts the information into ObjLog just as it
is,
Magine: while [LogObj] adjusts the object location information to make
it relative to the bot's location
ZebLith: oooh I see
Magine: so if @relsurv is 1, you get a "relative survey" and if @relsurv
is 0, you get a regular survey.
Magine: so all that making sense?
ZebLith: yes ^^
Magine: you getting a general idea of how things are done in the behavior
table?
ZebLith: much clearer now :)
Magine: well, we could keep going line by line in the table, but that
would take forever....so maybe we should at least skip to a different part
of the table and see how some different things besides surveys are done.
Magine: the next section is "remote control"....
Magine: this is where the bot responds to spoken commands.
Magine: found it?
ZebLith: yep :)
Magine: ok....as you can see there are a lot of rows there with Events
like HEAR @cmd[come], HEAR @cmd[follow] and so forth.
Magine: the @cmd there is a macro that looks in the chat string and
returns "true" (1) if the specified word is the first word of the chat
Magine: and if the chat has been directed at the bot, by using the
bot's name or by whispering.
Magine: if you were to look in userdefs.udf,
Magine: you would see @cmd defined as
Magine: @cmd[$]= (@tell&&@eq[$w1,~1])||@cmd_[~1]
Magine: which, as complicated as it looks :) only means
Magine: if the bot is being spoken to and the first word equals the
specified word, or if the first word begins with a / , then return 1
Magine: you can break down the (@tell&&@eq[$w1,~1])||@cmd_[~1]
Magine: into (@tell
&& @eq[$w1,~1])
|| @cmd_[~1]
[colors and fonts have been added here to identify the different parts]
[also note that the parentheses determine the order that the parts of
the expression are calculated]
Magine: which probably still seems pretty complicated i guess :D
ZebLith: a little... ^^
Magine: ok, one part at a time....
Magine: the @tell
part is just another macro, which returns true (1) if the chat is whispered
or if the first word of the chat is the bot's name
Magine: the @eq[$w1,~1]
part just means
Magine: does the first word of the chat string equal the word specified
in @cmd?
Magine: the ~1
refers to whatever parameter is first in the macro
Magine: so if you put @cmd[foobar]
Magine: then ~1
would be foobar
Magine: if you see what i mean :)
ZebLith: got that bit :)
Magine: the @cmd means "if the bot is being whispered
to, or the first word of the chat is the bot's name, AND the
first word of the chat not counting the bot's name is the specified word"
Magine: then added to all that is @cmd_[~1]
Magine: the @cmd_
macro returns true if the first word of the chat string is the specified
word prefaced by a slash /
Magine: so, if you wanted to tell the bot to come, for instance
Magine: you could say
Magine: mags come
[Mags]: Be right there.
Magine: or you could whisper just "come"
Magine: (to [Mags]) come
[Mags]: Be right there.
Magine: or you could say
Magine: /come
[Mags]: Be right there.
ZebLith: aaah :D
Magine: and all those different possibilites are contained in the single
@cmd macro
Magine: so instead of having to put
Magine: ((@botcmd||@whispered)&&@eq[$w1,foobar])||@eq[$w1,$cat["/",foobar]]
Magine: you can just put
Magine: @cmd[foobar]
Magine: and it means the same thing :)
ZebLith: and so much simpler! ;)
Magine: and actually $w1 is also a macro, so it would be even more
complicated than that :D
ZebLith: O_O lol
Magine: $w1 is a macro that returns the
first word of the chat string, not counting the bot's name if that is the
first word
Magine: so the whole thing would be the same as
Magine: ((@botcmd||@whispered)&&@eq[$word[@if[@eq[$botname,$word[1]],2,1]],foobar])||@eq[$word[@if[@eq[$botname,$word[1]],2,1]],$cat["/",foobar]]
Magine: lol :D
ZebLith: WAAAAAAAAY too long! X_x lol :D
Magine: so you can see that macros are indispensible
Magine: all that crap is contained in the simple @cmd macro
Magine: oh, no, it's still not fully expanded :D [because @botcmd
itself is a macro]
Magine: ((@eq[$botname,$word[1]]||@whispered)&&@eq[$word[@if[@eq[$botname,$word[1]],2,1]],foobar])||@eq[$word[@if[@eq[$botname,$word[1]],2,1]],$cat["/",foobar]]
And even that is still not the the whole thing, because to simplify just a bit, I also removed the part that checks to see if the first word of the chat string is an alias for the bot name, not just the bot name itself. So @botcmd is actually not just @eq[$botname,$word[1]], but is @eq[$botname,$word[1]]||@ind[$word[1],$v_[$cat["alias:",$botname]],"|"].Magine: there...anyway you get the point :D [which is, you can use macros within other macros to simplify things]
You can read more about expressions here,
and more about macros here.