MUDPROGS Latest update: April 1999 This is the second of 4 files on the topic of area writing. The advised order of reading is: 1. AREAFILE, dealing with the format of area files. 2. MUDPROG, dealing with MUDProgs. 3. AREAHELP, dealing with hints on building. 4. PROCEDUR, dealing with the procedure of turning in an area for Hesperia We STRONGLY advise you to read the GEO file as well, to get a good idea of our vision of Hesperia. What Are MUDProgs? Mudprogs are a way to make mobs, rooms and objects react to some events, like players walking into a room, examining an object, or saying a particular word or phrase. In general, it is a way to make the mud more vivid and less static. Not only can mobs, rooms and objects react to some things, also special effects can be introduced when mobs die, e.g. mages with health potions, who throw their potions on the ground, breaking them. It is for those special effects that there are certain special commands. Note The syntax looks the same as in the AREAfile, but there are differences. Here's an overview: <...> needed parameter, [...] optional parameter (may be included only once), '...' must be entered exactly like between the quotes. I will explain how the MUDProgs work, in this order: 1. The triggers will be introduced. Triggers activate the MUDProg. 2. What will be activated is a list of commands. These can consist of all the normal commands in the mud, like say, emote etc. In addition there are also special commands, these all start with "mp_" and will be explained later. Right after these commands, I will introduce variables. 3. Built in in the special commands are conditional expressions, so-called ifchecks: "if..then..else" constructions. After that, I will show how to add them to your AREA file, and present some examples. The Triggers I will now tell you which triggers you can use for rooms, objects and mobs. After that, I will explain all triggers. Mobs: bribe, death, all_greet, greet, entry ,fight, give, hitprcnt, rand, time, hour, script, act, speech Objs: greet, speech, rand, wear, use, remove, sac, get, drop, examine, zap, pull, push, act, trap Rooms:leave, enter, sleep, rest, rfight, death, speech, rand, act, rlook All progs with a percentage argument, are only triggered with a chance, equal to the argument. All [directions where player must come from] are strings, i.e. 'north', 'east', etc. -bribe_prog triggers if someone gives the mob an amount of money (or more) -death_prog triggers if a mob dies, with a chance of ...% -all_greet_prog [direction where player must come from] triggers on all entries, visible and invisible (yes, it includes wizinvis & mobinvis) -greet_prog [direction where player must come from] triggers when a visible character enters -entry_prog triggers when the mob enters a new room -fight_prog triggers every round the mob is fighting (8 times/tick) -give_prog |"all" triggers when someone gives the mob a certain item. 'all' triggers to all objects given to him. -hitprcnt_prog triggers when a mob has less than a percentage of hitpoints left. Place in increasing order, since only the first is processed -rand_prog triggers randomly -script_prog [hour] runs a list of commands one at a time. At the end of the list, it runs again. So once this list runs, there's no end to it. If you give an hour, it starts at the first time it is n o'clock -time_prog runs a list once at a specified (military) time -rour_prog runs a list for one hour, at specified time, then stops. A script_prog for one hour -speech_prog [p] triggers when someone says something to the mob. String consists of words that should trigger. If the optional 'p'- parameter is given, triggers if the words match exactly (don't forget punctiations, the last word of a sentence is appended with a '.', '!' or '?' !) -act_prog [p] triggers if someone performs an action. Reacts to the message displayed when the ation is performed. P-parameter for exact match. Hint: switch into the mob to see what message it gets. -leave_prog [direction the player must go to] triggers when someone leaves the room -enter_prog [direction where player must come from] triggers when someone enters the room (everybody) -sleep_prog when someone goes to sleep -rest_prog when someone rests -rfight_prog triggers when someone's fighting in the room -rlook_prog this can be used to generate random room descriptions, or different descriptions depending on where the players come from. Valid directions besides the obvious 'north', 'east', etc are 'all' and 'here'. 'Here' triggers when the player does a 'look' in the room, 'all' triggers always. Default is 'here'. Only the first trigger is executed, so you can make a trigger for 'north' and a second one 'all' which triggers in all other occasions. See the example below. -wear_prog if someone wears the object (includes wielding) -use_prog if someone uses the object (drink, eat, wear). Cannot have both a use- and a wear_prog on one object. -remove_prog if someone removes the object -sac_prog if someone sacs the object -get_prog if someone gets the object -drop_prog if someone drops the object -exa_prog if someone examines the object -zap_prog if someone is zapped by the object -pull_prog -push_prog works only with pullable/pushable objects: ITEM_LEVER, ITEM_SWITCH, ITEM_PULLCHAIN, ITEM_BUTTON Triggers when such an item is pulled/pushed -trap_prog used to generate the effects of an ITEM_TRAP and ITEM_TRAP_PC -ticket_prog used to generate the messages for coaching lines Special commands These commands can be used by all mobs, rooms and objects, unless noted otherwise. -mp_damage Damage someone for a certain amount of hitpoints -mp_damage_all Damages everybody in the room for a certain amount of damage (except for the mob doint this command). -mp_asound Display a message in the rooms around the person performing this command (the one who reacts to the trigger) -mp_echoaround Displays a message to everybody in the room except the person who caused the trigger and the one reacting to the trigger. If you start with a '.', it will skip the '.' (nice when you want to have spaces in front, or just print a newline) -mp_echoat Displays a message to the one who triggered the mob. If you start with a '.' it is skipped -mp_echo Displays a message to everybody in the room. If you start with a '.' it is skipped NOTE: mp_asound, mp_echoaround, mp_echoat and mp_echo will not display an uppercase letter if the phrase starts with a variable. In this case you should add '_u' at the end to get an uppercase letter. E.g.: mp_echo $n coughs loudly. --> mp_echo_u $n coughs loudly. -mp_kill Allows a mob to attack a player. This cannot be done by rooms and objects -mp_junk A mobile can distroy one of the items in his inventory, or equipment. If the argument is "all", all of his inventory and equipment is destroyed. "All." destroyes all items with a certain name -mp_mload loads a mob into the room -mp_oload [[level] [timer]] loads an item into inventory. Items that cannot be carried (i.e. without the ITEM_TAKE flag), are loaded into the room. If no level is given, the level of the object is the level of the mob which loads the object. If a timer is given, the object dissapears after n ticks (n=value) -mp_purge [name] lets a mobile purge all other mobs and object in a room, or a specific one. Yes, it is possible to purge oneself, but ugly things will happen, so please, don't try :) -mp_invis [level] just like wizinvis, but lets the mob set a level. Below that level he will not be seen. If no level is given, turns on/off -mp_goto works like the wizcommand 'goto'. Goes to a certain place (unless it is private) -mp_at Performs an action at an other location. Just like the wizcommand. -mp_transfer |"all" [location] Transfer all people in room to a location, or a specific person in the world. If location is ommited, location is the room the object/mob is in (or just the room itself) -mp_force |"all" Forces all people in the room, or someone in the world to do something. Works not on immortals -mp_practice Train someone in a certain skill, to percentage, unless he can't learn that much. Costs _no_ practices -mp_slay Slay a mob -mp_restore Restores someone's hp up to a certain maximum (or his maximum hp) -mp_restore '+' Restores a certain amount of hp to a char (up to his maximum) -mp_open_passage Opens a one-way passage from room1 to room2 in given direction (see the AREA file on directions), if there isn't one yet. -mp_close_passage Closes a passage opended with "mp_open_passage", if there is one. -mp_nothing Does nothing (useful in scripts) -mp_dream Sends a message to a sleeping character -mp_cast Casts a spell -mp_suppress Suppresses the output of the command which follows the mp_suppress. Usefull to avoid certain messages you don't want. -mp_track Makes the mob track (hunt down) a player. Once the mob finds his victim, the victim is attacked. -mp_oset Lets the mobile set the values of an object. Works the same as the immortal command. Variables Often, you want to know who caused the trigger, so you can use the commands mentioned above (or any other command) on him. Therefor there are variables: VARIABLE MOBILE ACTOR VICTIM RANDOM OBJECT 2ND_OBJECT -------------------------------------------------------------- - Name $i $n $t $r $o $p shrt_desc/title $I $N $T $R $O $P he/she/it $j $e $E $J -- -- him/her/it $k $m $M $K -- -- his/hers/its $l $s $S $L -- -- a/an -- -- -- -- $a $A newline * $_ Mobile is the mob/obj/room itself. Actor is the one who triggered, random is a random PC in the room. Object is for example the object given when a give_prog triggered. * Note: spaces, newlines, tabs, etc are skipped when they start a string. If you want to send only a newline, put a '.' in front of it, the '.' is skipped, the newline not. Example: Fletchez enters a room, and triggers a trap, therefore, he gets 10 damage, and a message: mp_echoat $n You hit a trap! mp_echoaround_u $n $n hits a trap, which wounds $m. mp_damage $n 10 Fletchez sees: 'You hit a trap!' and gets 10 damage. The others in the room see: 'Fletchez hits a trap, which wounds him.' Randall enters a room, in the room is his butler, who (of course) treats him with full egards: say Welcome, $N Everybody in the rooms now sees: The butler says 'Welcome, Randall The Dark Lord.' Conditional execution We want to introduce a way to react to a trigger only if the actor is a good character, or if there is a special item in the room. To solve this problem there are a whole bunch of ifchecks. Their syntax is as follows: 'if' [ ] [ 'else' ] 'endif' Where commands may contain nested if's (up to 20 levels). First an example, then a list of ifchecks. >all_greet_prog 100~ if isimmort($n) say Welcome, immortal else if level($n) < 50 say Go away, you tiny little being! mp_force $n south endif endif ~ | This is a simple program to lock the room for PC's who are not yet level 50, unless they are an immortal (i.e. trusted at an immortal level). This example shows the two kinds of ifchecks: isimmort is a function returning true or false, whereas level retuns an integer, which is then compared to another value (here 50). The following operators are defined: on strings: '==': is equal to, '!=': is not equal to, '/' : is substring of, '!/': is no substring of. Note that leading spaces are stripped, but you cannot be sure trailing spaces are also be stripped of. Be careful with editing, since 'guard' == ' guard', but 'guard'!='guard '. On integers: '==', '!=': is equal to, is not equal to. '<', '<=' : is less than, is less than or equal '>', '>=' : is more than, is more than or equal. Now the list of ifchecks, first the true/false checks: -mobinroom( vnum ) checks if a mob is in the room -ovnumhere( vnum ) -otypehere( string ) checks if there is an object in the room, in the mobs inventory or his equipment. ..vnum.. checks for a specific item, where ..type.. checks for an objecttype (e.g. "container" or "armor", see the AREA file) -ovnumroom( vnum ) -otyperoom( string ) checks if an item(type) is in the room -ovnumcarry( vnum ) -otypecarry( string ) checks if the mob has an item(type) in his inventory or his equipment -ovnumwear( vnum ) -otypewear( string ) checks if the mob has an item(type) in his equipment -ovnuminv( vnum ) -otypeinv( string ) checks if the mob has an item(type) in his inventory -ismobinvis( name ) checks if someone is mobinvis example: ismobinvis( $i ) checks if the mob itself is mobinvis -ispc( name ) -isnpc( name ) checks if someone is a PC(ispc), or a NPC(isnpc) -ismounted ( name ) checks if a person is mounted -isgood( name ) -isneutral( name ) -isevil( name ) checks someones alignment (note: this has nothing to do with which immortal that person is following!) isgood: 350 < alignment isneutral: -350 < alignment < 350 isevil: -350 < alignment -isfight( name ) checks if someone is fighting -isimmort( name ) checks if someone is an immortal -ischarmed( name ) checks if someone is charmed -isfollow( name ) checks if a person follows someone, and if they are both in the same room -rand( number ) Does a percentage check. Usefull with triggers which dont take a percentage as argument The following checks all take an operand and an operator: -timeskilled( name ) -timeskilled( vnum ) for every mobvnum there is a counter for how many times it is killed. This check returns the number of times this mob was killed. Don't try this on PC, I really don't what will happen. So first an 'if isnpc(....)'. -mobinvislevel( name ) returns the mobinvis level of a character. PC's have 0 -isaffected( name ) '==' affect checks if a character is affected by something example: isaffected( $i ) == poison checks if the mob is poisoned -personwear( name ) '==' vnum -personcarry( name ) '==' vnum -personhas( name ) '==' vnum checks if a person has a certain vnum in his equipment, inventory, or both. -someone_has_light( name ) checks if a person is in a room, lit by someone in that room. -hitprcnt( name ) returns how hurt somebody is -inroom( name ) returns where someone is (room vnum) -sex( name ) returns the sex of someone (0=neutral, 1=male, 2=female) -position( name ) returns the position of someone ( DROWNING = 0, DEAD = 1, MORTAL = 2, INCAP = 3, STUNNED = 4, SLEEPING = 5, RESTING = 6, FIGHTING = 7, STANDING = 8) -level( name ) returns the effective level of someone -sublevel( name ) returns the effective Acolyte sublevel of someone -goldamt( name ) returns how much money someone has in cash -class( name ) returns the 3-letter string which identifies a class (e.g. mag=mage, rog=rogue) -race( name ) returns the race of someone (note: races start with a capital, e.g. Human) -str( name ) -dex( name ) -int( name ) -con( name ) -wis( name ) returns the strength, dexterity, intelligence, constitution and wisdom of a character -objtype( name|vnum ) returns the type of an object (integer) -objval0( name|vnum ) -objval1( name|vnum ) -objval2( name|vnum ) -objval3( name|vnum ) return the values of an object. See the AREA-file for the meanings of the different values for different types -number( name ) if checked on the mob itself, it returns the amount of gold he has, else returns the vnum of the mob/object referred to -name( name ) returns the name of someone. Usefull when the argument is a variable. if name($n) == Randall... -religion( name ) returns the religion of a char (0=none, 1=dark, 2=neutral, 3=covenant) -immortal( name ) returns the immortal someone is following Adding Mudprogs AREA-files We have covered all aspects of the MUDProgs now. It's time for me to show how you can put this in your area files. It goes the same for rooms, objects, and mobs. After the definition of a mob, object or room, put the following construction: '>in_file_prog' '~' This associates a MUDProgram-file with a mob, object or room. The file must look like this: [ '#' ] . . [ '#' ] '>' '~' . . '~' '>' '~' etc. End the list of triggers with a '|'. Make sure you use the first few lines to tell what the program is doing. That way we can make a list with programs, so you do not have to invent the wheel over and over again. Lets look at some examples: Imagine a dark forest, where the flowers say they want to kill you, and when you sleep, you get nightmares. A flowerprog may look like this: > greet_prog 75~ mpechoat $n A flower whispers 'Die... Die... Die...' ~ | Everyone who enters now has a 75% chance of hearing a flower whispering 'Die... Die... Die...'. Note that this flower is implemented as an object. A mob with ACT_SENTINEL would do to, both have the same MUDProg. This explains the file, now lets associate this file (which we will save as 'flower.prg') with the flower: #vnum . . (names, values, etc) . >in_file_prog flower.prg~ To make the nighmare part, we add this to a room: #vnum . . > in_file_prog nightmar.prg~ And make the associated program: >sleep_prog 100~ mp_dream $n When you sleep, you dream about het most fiercefull creatures, coming to get you. In horror, you wake up. mp_force $n wake ~ | Note: the mp_dream line should have no enters in it, just type it in one sentence. For the next example, consider the Lord of Allerheim. Suppose a player could sneak past his guards, and starts fighting, our Lord screams for his guards, who come to save the Lord. The next prog would do for the Lord: >fight_prog 100~ mp_at eliteguard say help yell Guards, guards! ~ | The guards react to this: >speech_prog help goto lord mp_echo The guard comes to rescue his master. mp_kill $r ~ | Note that for smaller mudprogs it is allowed to add them directly in the area. Larger mudprogs which are used multiple times in an area are ideal to use put in a file and load into an area with an '>in_file_prog'. Some Extended Examples The next examples make use of all things mentioned above. The first example is a prog, which makes some sort of shopkeeper. When a PC enters his room, there is a 25% chance of him offering his special item (in this case a parchment which leads to a treaure or something). The vnum of the item is 1003. He won't tell the price right away, players have to ask him that. When they give him the right amount, he will give them the item, and destroy the coins in his inventory (so they cannot kill him later and get their money back: > all_greet_prog 25~ if ispc($n) mp_echoat $n A man hidden in the shadows beckons you over to him. tell $n I have some information which may be of some value... tell $n And for a price I will perhaps share it with you. endif ~ > speech_prog p how much~ if ispc($n) mp_echoat $n The dark figure stares unflinchingly into your eyes. mp_echoaround_u $n $I draws close to $n and says something. mp_echoat_u $n $I matter-of-factly says, '4,500 gold pieces.' endif ~ > speech_prog p what price~ if ispc($n) mp_echoat $n The dark figure stares unflinchingly into your eyes. mp_echoaround_u $n $I draws close to $n and says something. mp_echoat_u $n $I matter-of-factly says, '4,500 gold pieces.' endif ~ > speech_prog p how much?~ if ispc($n) mp_echoat $n The dark figure stares unflinchingly into your eyes. mp_echoaround_u $n $I draws close to $n and says something. mp_echoat_u $n $I matter-of-factly says, '4,500 gold pieces.' endif ~ > speech_prog p what price?~ if ispc($n) mp_echoat $n The dark figure stares unflinchingly into your eyes. mp_echoaround_u $n $I draws close to $n and says something. mp_echoat_u $n $I matter-of-factly says, '4,500 gold pieces.' endif ~ > bribe_prog 4500~ mp_echoaround $n $I quickly tucks the coins inside his shroud, stepping toward $n. mp_echoat_u $n $I quickly tucks the coins inside his shroud, and says: mp_echoat $n 'I took this from a man... a weak, sniveling man I was to kill.' mp_echoat $n He continues, 'He traded me the artifact in exchange for his life.' , sneers mp_echoat $n The figure says, 'Lucky was he the price on his head was low...' mp_echoat $n He produces a strange, tied parchment from his shroud. mpoload 1003 5 give parchment $n mpjunk all.parchment mpjunk all.coins say Good ... doing business ... with you, $n. , backs into the shadows. ~ | Note the double checks on what players ask: with and without a questionmark. Also note the use of emote (',') the make him do things which everybody in the room sees. Now a smaller example: > death_prog 100~ mpechoat $n You hear a ghastly howl. say You think you may have killed me, but I will be avenged! mpechoat $n Another demon is quickly pushed from the shadows. mpmload 21434 mp_force demon mp_kill $n ~ | This loads another mob, when the mob dies, and forces the new mob to attack the one who caused him to die. Now some beggar prog: this beggar likes dogs, so if a dog enters, he will be nice to it. If someone else enters, he will ask for some coins. If he gets a lot of coins, he will be so surprised, his heart stops. As this happens, he will force the cleric (who is at a fixed place) to purge him (this mob's name is 'beggarprog'): > all_greet_prog 100~ if name($n) == dog stray emote pets the dog. mp_force stray lick beggar say That's a good boy, here's a small treat. mp_echo The beggar tosses a scrap of meat across the road. mp_echo The stray quickly chases after it, eager to fill his belly. else say Could you spare a few coins please? beg $n endif ~ > rand_prog 5~ emote rummages in one of many pouches, searching for gold no doubt. ~ > bribe_prog 1000~ say OHHH MY!!! mp_echo The beggar suddenly clutches his chest and doubles over. mp_echo In the blink of an eye, he is dead. mp_echo The surprise and shock must have been too much for him. mp_at 21194 mp_force cleric mp_at beggarprog mp_purge beggarprog ~ > bribe_prog 100~ say I cannot express my gratitude in words $n! kiss $n say If only others were so generous. ~ > bribe_prog 10~ say Thank you for such a worthy donation. thank $n ~ | This example generates random room descriptions. Imagine walking towards an active volcano in the north, it gets hotter and hotter with every step. Walking back, the temperature drops again. The $cx and $ca are there to generate the right color codes for the room description. Notice these are only small room descripts to show the workings. Normally room descripts should at least be 3 lines of about 75 characters. > rlook_prog north~ mp_echoat $n $cxAs you move closer to the volcano, you begin to feel great mp_echoat $n heat from that direction.$ca ~ > rlook_prog south~ mp_echoat $n $cxWalking away from the volcano, you feel the fresh air cools mp_echoat $n your face.$ca ~ > rlook_prog here~ mp_echoat $n $cxStanding a few meters from the volcano, you can see the hot mp_echoat $n lava bubbling inside of it.$ca ~ | My last example will be a hidden door. In room 1001 there is a bush, hiding a entrance to the north into room 1002. When someone examines the bush, he may uncover the entrance. This prog is for the bush: > exa_prog 33~ mp_echoat $n When you look at the bushes, you notice something in it. mp_echoat $n Upon taking a closer look, you see there is an entrance. mp_echoaround_u $n $n discovers something in the bushes! mp_open_passage 1001 1002 0 ~ >rand_prog 66~ mp_close_passage 1001 0 ~ | This is not a good way to make the hidden door. Better make a normal exit and make it hidden, having the MUDProg tell there is an exit to the north. However, the use of the passages is made clear, just as I attempted. I hope these examples explained things a bit. Final Comments I hope I succeeded in telling you how you should make MUDProgs. As with all programming languages, you should play around a bit with it to get a grip on it. So start with trivial things, and increase the level of your progs step by step. If you have an idea, but you cannot write it down, or it just won't work, write me. Also if anything in this file isn't clear, tell me, and I will try to explain it to you. If you feel the need for extra triggers, or for extra checks, tell me, they are fairly easy to add, and I will try to quickly implement the new triggers and ifchecks. However, as with all good things there is a drawback. The mud slows down a bit with every trigger you add. This has no big effect, when you are writing roomprogs, because there is only one instance of a room present in the mud. Things get worse with mobs. Of most mobs more copies wander around, every mob checking his triggers from time to time. Things get real bad with takable items. Suppose some popular item would have a mudprog with it. For everyone who gets the item, and doesn't sac it, there will be a trigger. It isn't impossible for having 20 of those items wandering around in the mud. This way, the mud slows down top much. So don't give every mob/item/room a prog. Be selective, that way it does also remain a special feature, like it was meant to be. (c) Randall, 1997 Comments: fletchez@panic.et.tudelft.nl