Section 9:    #MOBPROGS

This is the section where the actual code of the mobprograms is located. First of all, we should take a look at the variables that can be used in the mobprograms. One general notice beforehand: You do not need to use VNums for the mobprograms. Dawn of the Ages also accepts any phrase as a header for a mobprogram or for a mobscript. For example you can call your mobprogram '#myprogi1', if you wish.

  1. Variables

    Here's a brief overview:

    Variable Mobile Actor Victim Random Target Object 2nd_Object
    name $i $n $t $r $q $o $p
    shrt_desc/title $I $N $T $R $Q $O $P
    he/she/it $j $e $E $J $X - -
    him/her/it $l $m $M $L $Y - -
    his/hers/its $k $s $S $K $Z - -
    a/an - - - - - - -

    Now for a bit more detail.

    To make things come alive, variables are needed. These are represented in the MOBprograms by using a dollar sign convention as in the socials. When the mud command is processed, these variables are expanded into the values shown below. Usually, it is best to use the short descriptions of mobiles and the names of players when speaking them, but if you are performing an action to someone almost always you want the name. The title field for players is an extra that probably wont often be used.

    $i the first of the names of the mobile itself.
    $I the short description of the mobile itself.
    $n the name of whomever caused the trigger to happen.
    $N the name and title of whomever caused the trigger to happen.
    $t the name of a secondary character target (i.e A smiles at B)
    $T the short description, or name and title of target (NPC vs PC)
    $r the name of a random PC in the room with the mobile
    $R the short description, or name and title of the random PC
    $q the name of the MOBprogram target (see MOB REMEMBER)
    $Q the short description of the MOBprogram target
    $j he,she,it based on sex of $i.
    $e he,she,it based on sex of $n.
    $E he,she,it based on sex of $t.
    $J he,she,it based on sex of $r.
    $k him,her,it based on sex of $i.
    $m him,her,it based on sex of $n.
    $M him,her,it based on sex of $t.
    $K him,her,it based on sex of $r.
    $l his,hers,its based on sex of $i.
    $s his,hers,its based on sex of $n.
    $S his,hers,its based on sex of $t.
    $L his,hers,its based on sex of $r.
    $o the first of the names of the primary object (i.e A drops B)
    $O the short description of the primary object
    $p the first of the names of the secondary object (i.e A puts B in C)
    $P the short description of the secondary object

    Also, in if_checks, the accepted variables are the basic ones (i,n,t,r,o,p,q). If a variable is referenced that doesn't exist, then the value is simply left blank or replaced with "someone"/"something" in output (i.e referring to $o when the trigger is: A kisses B).

    If variable $q has not been defined, it is automatically set to the last player that has triggered the program being executed (i.e. variable $n). Once $q has been defined, it can be modified with MOB REMEMBER and MOB FORGET commands in a program. Variable $q lets the mobile "remember" a player across different programs, which can be useful. Note that $q is set automatically only the FIRST TIME the mobile executes a program, every time thereafter it must be set with MOB REMEMBER.

    The only problem with the variables is that the secondary object and the secondary target are passed by act() in the same location. This means that if you reference $t in an A puts B in C situation, the result will probably be a happy mud crash or some weird side effect, espescially if $t is used in an if_check (i.e. if isnpc($t) in the above situation). The basic fix for this is to change everyone who calls the act() procedure to specify a secondary object and a secondary character. But that is a fairly comprehensive trivial twiddle, so we left it the way it is so you aren't forced to make all those twiddles to use the MOBprograms.

  2. Control Flow Syntax

    In place of any legal mud command in a MOBprogram, one can substitute a flow of control command. Here is the syntax for a flow of control command. The parts between [ and ] are optional.

    "if" " " {if_check_1} {argument} [ {operator} {value} ] NL
    [ "or" " " {if_check_2} {argument} [ {operator} {value} ] NL ]
    [ "or" " " {if_check_N} {argument} [ {operator} {value} ] NL ]
    . . .
    [ "and" " " {if_check_N} {argument} [ {operator} {value} ] NL ]
    [ "and" " " {if_check_N} {argument} [ {operator} {value} ] NL ]
                .    .        .

    [ {program_command_1} NL ]
    [ {program_command_2} NL ]
    . . .
    [ "break" NL ]
    . . .
    [ {program_command_N} NL ]

    [ "else" NL ]

    [ {program_command_1} NL ]
    [ {program_command_2} NL ]
    . . .
    [ "break" NL ]
    . . .
    [ {program_command_N} NL ]

    "endif" NL

    Basically, it is: an 'if' line, followed by zero or more 'or' lines, followed by zero or more 'and' lines ('and' and 'or' lines can be in any order) followed by zero or more legal mud commands, which may contain a 'break' line, possibly followed by an 'else' line , followed by zero or more legal mud commands, which may contain a 'break' line, followed by an 'endif' line.

    The only new syntax labels are all in the IF/OR/AND line:

    --Explanations

    An IF_CHECK is a string which describes under what context to compare things. The ARGUMENT is the reference point from which the LHS of an expression comes. The OPERATOR indicates how the LHS and RHS are going to be compared. The VALUE is the RHS of the expression to be compared by the operator. The BREAK command bails out of the entire MOBprogram regardless of the level if nesting. (END is a synonym for BREAK). If that looks confusing, skip to the end of the document and review the examples. Hopefully that should clear things, otherwise you'll probably have to give me a mail since examples are the best way I know to explain syntax.

  3. Operators

    Most of the basic numeric operators are legal and perform the same function as in C.

    Operators: == != > < >= <=

  4. If_Checks in Control Flow

    The provided list of if_checks and their arguments are below. They should all be fairly obvious in what they do, but some of the more obtuse deserve a slight explanation. Any '==' operator can be replaced with any of the available ones described above. The argument $* refers to any of the variables which make sense for that if_check (i.e. for an if_check which is referencing a person the only valid variables would be $i, $n, $t, $r or $q) A value type of string is a sequence of characters. It needs to be included in quotes if it contains spaces (i.e. tell $n 'I would rather you didnt poke me.').

    There are five types of if checks:

    Type 1: Keyword and value

    rand num Is random percentage less than or equal to num
    mobhere vnum Is a NPC with this vnum in the room
    mobhere name Is a NPC with this name in the room
    itemhere vnum Is an object with this vnum in the room
    itemhere name Is an object with this name in the room
    mobexists name Does NPC 'name' exist somewhere in the world
    itemexists name Does object 'name' exist somewhere in the world

    Type 2: Keyword, comparison and value

    people == integer Is the number of people in the room equal to integer
    players == integer Is the number of PCs in the room equal to integer
    mobs == integer Is the number of NPCs in the room equal to integer
    clones == integer Is the number of NPCs in the room with the same vnum as the NPC who activated the program equal to integer
    order == integer Is the order (of several similar NPCs) of the NPC who activated the trigger equal to integer
    hour == integer Is the hour (game time) equal to integer

    Type 3: Keyword and actor

    isnpc $* Is $* an NPC
    ispc $* Is $* a PC
    isgood $* Does $* have a good alignment
    isneutral $* Does $* have a neutral alignment
    isevil $* Does $* have an evil alignment
    isimmort $* Is $* an immortal (level of $* > LEVEL_HERO)
    ischarm $* Is $* affected by charm
    isfollow $* Is $* a follower with their master in the room
    isactive $* Is $*'s position > POS_SLEEPING
    isdelay $* Does $* have a delayed MOBprogram pending
    isvisible $* Is $* visible to NPC who activated the program
    hastarget $* Does $* have a MOBprogram target in the room
    istarget $* Is $* the target of NPC who activated the program
    isarmed $* checks whether the mob is armed or not
    isfighting $* Is $* fighting?
    hascareer $* Does $* have a career?
    hasscript $* Does $* have a script running?
    ishuntingjudge $* Is $* a hunting Judge?

    Type 4: Keyword, actor and value

    affected $* 'affect' Is $* affected by 'affect'
    act $* 'act' Is $*'s ACT bit 'act' set
    off $* 'off' Is $*'s OFF bit 'off' set
    imm $* 'imm' Is $*'s IMM bit 'imm' set
    carries $* 'name' Is $* carrying object 'name' or vnum
    wears $* 'name' Is $* wearing object 'name' or vnum
    has $* 'type' Does $* have object of item_type 'type'
    uses $* 'type' Is $* wearing object of item_type 'type'
    name $* 'name' Is $*'s name 'name'
    pos $* 'position' Is $*'s position 'position' (sleeping etc.)
    race $* 'name' Is $* of race 'name'
    itemtype $* 'type' Is $*'s item_type 'type'

    Type 5: Keyword, actor, comparison and value

    vnum $* == integer Is $*'s virtual number equal to integer
    hpcnt $* == integer Is $*'s hitpoint percentage equal to integer
    room $* == integer Is vnum of the room $* is in equal to integer
    sex $* == string Is $*'s sex equal to 'male', 'female' or 'neutral'
    level $* == integer Is $*'s level equal to integer
    align $* == integer Is $*'s alignment equal to integer
    money $* == integer Does $* have money (in silver) equal to integer
    itemval# $* == integer Is $*->value[#] equal to integer (# from 0-4)
    pkpower $* == integer Is $*'s pkpower equal to integer
    class $* == string Is $*'s class equal to 'string'
    religion $* == string Is $*'s religion equal to 'string'
    clan $* == string Does $* belong to clan 'string'
    career $* == string Is $*'s career 'string'

    NOTE: The original MERC 2.2 MOBprograms used parenthesis '(' and ')' around variables. In this version, they are not allowed. Also, parameters MUST BE separated with spaces (if level $n<10 is NOT valid, correct syntax is: if level $n < 10).

    ANOTHER NOTE: Remember that you can use all above specified operators, not just ==.

  5. Mobcommands

    MOBcommands are special commands that allow mobiles to perform immortal-like actions within a MOBprogram (transferring players or loading items, for example). Most MOBcommands themselves are wiz commands which have been changed to allow for mobiles to perform the commands. In this version of MOBprograms, players have been prevented from using these commands by adding a separate interpreter for MOBcommands. This also speeds up (in most cases) MOBprogram execution when MOBcommands are used. All MOBcommands are preceded with the word 'MOB' on the command line.

    MOB ASOUND [string]
    MOB ZECHO [string]
    MOB GECHO [string]

    ASOUND prints the text string to the rooms around the mobile in the same manner as a death cry. This is really useful for powerful aggressives and is also nice for wandering minstrels or mobiles like that in concept. ZECHO prints the string to all players in the same area with the mobile. GECHO prints the string to all players in the game. Please remember, strings containing spaces must be surrounded by quotes.

    MOB ECHO [string]
    MOB ECHOAT [victim] [string]
    MOB ECHOAROUND [victim] [string]

    ECHO displays the string to everyone in the room. ECHOAT displays the string to the victim only. ECHOAROUND displays the string to everyone except the victim. The three options let you tailor the message to goto victims or to do things sneaky like having a merchant do:

    mob at guard mob echoat guard rescue_please

    This coupled with a guard act trigger on rescue_please to:

    mob goto $n
    mob echo $I has arrived.
    

    It is an affective way of quickly bringing guards to the scene of an attack. (Note that the merchant has to be the only one of its kind in the game or have a unique name, otherwise the guard might go to different mobile...).

    MOB MLOAD [vnum]
    MOB ILOAD [vnum] {'room'|'wear'}

    MLOAD creates a mobile and places it in the same room with the mobile. ILOAD loads the object into the inventory of the mobile. Even if the item is non-takable, the mobile will receive it in the inventory. This lets a mobile distribute a quest item or load a key or something. The optional 3rd parameter can be specified; 'room' means to load the object to the room, 'wear' means to force the mobile to wear the object loaded (useful for equipping mobiles on the fly).

    MOB REMOVE [victim] [vnum|'all']

    Lets the mobile to strip an object of given vnum from the victim. Objects removed are destroyed. If the vnum is replaced with "all", the whole inventory of the victim is destroyed. This command is probably most useful for extracting quest items from a player after a quest has been completed.

    MOB JUNK [object]

    Destroys the object refered to in the mobile's inventory. It prints no message to the world and you can do things like junk all.bread or junk all. This is nice for having janitor mobiles clean out their inventory if they are carrying too much (have a MOBprogram trigger on the 'full inventory'.)

    MOB PURGE [argument]

    Destroys the argument from the room of the mobile. Without an argument the result is the cleansing of all NPC's and items from the room with the exception of the mobile itself. However, mppurge $i will indeed purge the mobile, but it MUST be the last command the mobile tries to do, otherwise the mud cant reference the acting mobile trying to do the commands and bad things happen.

    * MOB AT [location] [command]

    Perfoms the command at the designated location. Very useful for doing magic slight of hand tricks that leave players dumbfounded.. such as metamorphing mobiles, or guard summoning, or corpse vanishing.

    MOB GOTO [location]

    Moves the mobile to the room or mobile or object requested. It makes no message of its departure or of its entrance, so these must be supplied with echo commands if they are desired.

    MOB TRANSFER [victim|'all'] [location]
    MOB GTRANSFER [victim] [location]
    * MOB OTRANSFER [object] [location]

    Sends the victim to the destination or to the room of the mobile as a default. if the victim is "all" then all the characters in the room of the mobile are transfered to the destination. Good for starting quests or things like that. There is no message given to the player that it has been transfered and the player doesnt do a look at the new room unless the mob forces them to. Gtransfer works like transfer, except that the group the victim belongs to is transferred with the victim. Otransfer transfers an object in the room.

    MOB FTRANSFER [victim] [location] [clan|profession|religion|race|align|mobs|charmies]

    Sends the victim to the room given by [location]. The first and second arguments are necessary; the third argument is optional. If you omit the third argument from the mobcommand, the mobile will transfer all of the character's followers to the location. If you use the third argument, the mob will transfer only those followers that conform to the argument, e.g., if "charmies" is used, then the player and all charmed followers of the player will be transferred.

    MOB FORCE [victim|'all'] [command]
    MOB GFORCE [victim] [command]
    MOB VFORCE [vnum] [command]

    Forces the victim to do the designated command. The victim is not told that they are forced, they just do the command so usually some mpecho message is nice. You can force players to remove belongings and give them to you, etc. The player sees the normal command messages (such as removing the item and giving it away in the above example) Again, if the victim is "all" then everyone in the mobiles room does the command. Gforce works like force except that it affects the group the victim belongs to. Vforce affects all mobiles with given vnum in the game world. This is useful for, for example, purging certain type of NPCs from the game (by forcing them to purge themselves).

    MOB CAST [spell] [victim]

    Lets the mobile to cast spells. Beware, this does only crude validity checking and does not use up any mana. All spells are available regardless of the race or other abilities of the mobile. Casting the spell occurs silently, but spell effects are displayed normally.

    MOB DAMAGE [victim|'all'] [min] [max] {lethal}

    Causes unconditional damage to the victim. Specifying "all" as victim causes damage to all characters in the room except the mobile. Min and max parameters define the minimum and maximum amounts of damage caused. By default, the damage is non-lethal, but by supplying the optional 'lethal' parameter, the damage can kill the victim. This command is silent, you must echo all messages yourself in the program. Useful for implementing special attacks for mobiles.

    MOB DELAY
    MOB CANCEL

    MOB DELAY sets the time in PULSE_MOBILE after which the mobile's delay trigger is activated. If the mobile has a program defined for delay trigger, the program is executed when the timer expires. MOB CANCEL resets the delay timer.

    MOB REMEMBER [victim] MOB FORGET

    This command enables the mobile to remember a player for future reference in a MOBprogram. The player can subsequently be referred as '$q' in programs activated by the mobile. MOB FORGET clears the target. Note that if the first time the mobile runs a program, $q is automatically set to the player who triggered the event. Most commonly this command is used in delayed programs, where the mobile has to remember the player who triggered the original event, for example to continue conversation.

    MOB CALL [vnum] {victim} {target1} {target2}

    This command lets you call MOBprograms from within a running one, i.e. to call a MOBprogram subroutine. The first parameter is the vnum of the program to execute, the second is the victim's name (for example $n), and the third and fourth are optional object names. All other parameters except vnum can be replaced with word 'null' indicating ignored parameter. MOBprograms can be called recursively, but as a safety measure, parser allows only 5 recursions.

    MOB REWARDQPTS [victim] [minQpts] [maxQpts]

    This command gives you the opportunity to hand out questpoints via a mobprogram for solved quests. You can also decrease the questpoints of the victim by applying negative numbers for minQpts and maxQpts.

    * Not yet implemented.

  6. Loading Mobiles and Objects

    No doubt you want to load objects and mobiles in your MOBprograms with "mob oload" and "mob mload". There are two problems connected to this. One is that mloaded mobiles will appear without equipment and the other is that it is difficult to keep track of the number of created mobiles and objects. If you want to mobiles to appear in your area as a result of the players' action, create a "storage room". Define resets for the mobiles as usual (equipment etc.) and place them in the storage room. When you need to use the mobiles, just "mob transfer" them to the location you want. This is better than creating mobiles on the fly, since you don't have to worry about creating too many mobiles or equipping them, area resets take care of all that. If you have a MOBprogram that creates new mobiles, you might want to make the mobiles "self-destructing". This is easiest to do with a random trigger that checks if the mobile is doing anything useful and possibly does 'mob purge $i'. Another possibility is to use a "purgemaster". Create a storage room with a single mobile. Attach a random trigger that does 'mob purge' to that mobile. Now, when you need to get rid of anything, just 'mob transfer' the mobile or item to purgemaster, and it will be destroyed sometime later.

  7. Examples

    In #MOBILES:

    M act 1000 pokes you in the ribs.~

    In #MOBPROGS:

    #1000
    if isnpc $n
        chuckle
        poke $n
        break
    else
        if level $n <= 5
        or isgood $n
            tell $n I would rather you didnt poke me.
        else
            if level $n > 15
                scream
                say Ya know $n. I hate being poked!!!
                if mobhere guard
                    mob force guard kill $n
                endif
                kill $n
                break
            endif
            slap $n
            shout MOMMY!!! $N is poking me.
        endif
    endif
    ~
    

    Ok.. time to translate.. the trigger will only happen when the mobile gets the message "... pokes you in the ..." If the offender (recall the $n and $N refer to the char who did the poking...) is an NPC, then the mobile merely chuckles and pokes back. If the offender was a PC then good and low level characters get a warning, high level chars get attacked, and midlevel chars get slapped and whined at. Also, when attacking, the mobile will check if there are guards in the room (if mobhere guard) and if one is found, it will be forced to attack the player, too (mob force guard mob kill $n). Notice the use of a MOBcommand "mob force".

    Note that two of these mobiles could easily get into an infinite poke war which slows down (or frequently crashes) the mud just a bit :( Be very careful about things like that if you can. (i.e dont respond to a poke with a poke, and try not to let heavily programmed robot mobiles wander around together. More on that is given above.)

    Also, it is clear that the 'order' command could get confused with the 'or' control flow. However, this is only the case when 'order' is abbreviated to its two letter form, and placed immediately following an 'if' line. Thus, if you want to be that malicious in trying to break the MOBprogram code, noone is going to stand in your way (However, the result of this would be a bug message and a bail out from the ifcheck so things don't really break.)

    Another example:

    This program could be used on a temple guardian mobile, whose job is to prevent evil characters from entering the sanctuary. Let's assume the exit to the temple is north (exit 0) and the temple antechamber is room 2301

    In #MOBILES:

    M exit 1001 0

    In #MOBPROGS

    #1001
    if isgood $n
        say Hail!
        emote salutes $n.
        if carries $n holy
            mob transfer $n 2301
        else
            say If you wish to enter the temple, get a holy symbol.
        endif
    else
        curse $n
        say Get lost, you scum!
    endif
    ~
    

    How this works: The trigger is activated when the player tries to exit north from the room. If the player is of good alignment, the guard will greet the player. However, the guard will not let the player to the temple unless he or she carries a holy symbol. If the player is neutral or evil, the guard will curse and block the way.

    Example of using DELAY and REMEMBER:

    In #MOBILES:

    M greet 1002 100
    M delay 1003 100
    

    In #MOBPROGS

    #1002
    if isevil $n
        say You infidel! Go away or face the wrath of mighty Mota!
        mob remember $n
        mob delay 10
        break
    endif
    ~
    #1003
    if hastarget $i
        growl
        mob echo $I screams and attacks $Q.
        kill $q
    else
        mob forget
    endif
    ~
    

    How this works: When the player enters a room, the mobile checks if the player is evil. If this is the case, the mobile makes the player the target (mob remember) and sets up a delay of 10 * PULSE_MOBILE. When the delay expires, program #1003 is activated. The mobile checks if the target is still in the room (hastarget), and if the player hasn't left, the mobile attacks ($q and $Q refer to the target). If the player has left, the mobile will forget the player (mob forget).

    Example of MOB CALL:

    In #MOBILES:

    M greet 1004 100

    In #MOBPROGS

    #1004
    if isgood $n
        mob call 1005 $n null null
    else
        mob call 1006 $n null null
    endif
    ~
    #1005
    mob echo Suddenly, a bright aura surrounds $I!
    mob cast 'heal' $n
    ~
    #1006
    mob echoat $n $I points $l finger at you in fury!
    mob echoaround $I points $l finger at $N in fury!
    mob cast 'curse' $n
    ~
    

    BTW, you can always use comments within the mobprogs. Just start the line with a semi-colon (;).

    You close the #MOBPROGS-section with a #0.