This is an updated version of the mount code. It works fine under bpl 21/22. This was not much of an update (as you can see by the fact that I managed it) but I figured I would at least provide a listing of changes so other folks can refer to the changes I made. May save a few minutes. (That and the fact that I removed all my .c files and had to add the mount code a second time. *doh* I figured I may as well make it worth something.) This is not a patch, it is a walkthrough. I always handpatch or use walkthroughs when adding snippets, and I think it is a vastly better way to go about things. This should allow you to get better at understanding all of the code, and particularly the code you are inserting. Really good programmers can probably fire and forget (if they trust the source of the patch). But really good programmers can also write their own mount system which is custom tailored to their own mud. :) I have included the readme from the original release at the bottom, plus the brief note from Mike Sulmicki who fixed a couple of bugs inherent in the original release. Credit is not needed, if you credit everyone who ever talked to you about a mud, you can add me. Other than that, it is the mount code dak submitted long ago in 1996. (And if you do credit me, credit Mike Sulmicki too, because he fixed bugs, I just updated.) Success! -Mathew Earle Reuther (aka Corwynn) *** Changes made to bpl21/22 for the dak mount system: BEGIN MOUNT CODE WALKTHROUGH BEGIN ACT.INFORMATIVE.C In look_at_char, after the call to diag_char_to_char, add: + if (RIDING(i) && RIDING(i)->in_room == i->in_room) { + if (RIDING(i) == ch) + act("$e is mounted on you.", FALSE, i, 0, ch, TO_VICT); + else { + snprintf(buf2, sizeof(buf2), "$e is mounted upon %s.", PERS(RIDING(i), ch)); + act(buf2, FALSE, i, 0, ch, TO_VICT); + } + } else if (RIDDEN_BY(i) && RIDDEN_BY(i)->in_room == i->in_room) { + if (RIDDEN_BY(i) == ch) + act("You are mounted upon $m.", FALSE, i, 0, ch, TO_VICT); + else { + snprintf(buf2, sizeof(buf2), "$e is mounted by %s.", PERS(RIDDEN_BY(i), ch)); + act(buf2, FALSE, i, 0, ch, TO_VICT); + } + } Further down in list_one_char, after the flags are listed, add/modify thus: + if (RIDING(i) && RIDING(i)->in_room == i->in_room) { + send_to_char(ch, " is here, mounted upon "); + if (RIDING(i) == ch) + send_to_char(ch, "you"); + else + send_to_char(ch, "%s", PERS(RIDING(i), ch)); + send_to_char(ch, "."); ! } else if (GET_POS(i) != POS_FIGHTING) A bit further down, change your list_char_to_char slightly: for (i = list; i; i = i->next_in_room) if (ch != i) { + if (RIDDEN_BY(i) && RIDDEN_BY(i)->in_room == i->in_room) + continue; if (CAN_SEE(ch, i)) list_one_char(i, ch); END ACT.INFORMATIVE.C BEGIN ACT.MOVEMENT.C Where external function protoypes are listed, add: + void dismount_char(struct char_data * ch); + void mount_char(struct char_data *ch, struct char_data *mount); In do_simple_move where variables are declared, add: + int same_room = 0, riding = 0, ridden_by = 0; + char buf2[MAX_STRING_LENGTH]; In do_simple_move, just before the check for charmed, add: + /* check if they're mounted */ + if (RIDING(ch)) riding = 1; + if (RIDDEN_BY(ch)) ridden_by = 1; + + /* if they're mounted, are they in the same room w/ their mount(ee)? */ + if (riding && RIDING(ch)->in_room == ch->in_room) + same_room = 1; + else if (ridden_by && RIDDEN_BY(ch)->in_room == ch->in_room) + same_room = 1; + + /* tamed mobiles cannot move about (DAK) */ + if (ridden_by && same_room && AFF_FLAGGED(ch, AFF_TAMED)) { + send_to_char(ch, "You've been tamed. Now act it!\r\n"); + return 0; + } In do_simple_move, modify the line which checks for a boat: ! if ((riding && !has_boat(RIDING(ch))) || !has_boat(ch)) { In do_simple_move, after movement points are averaged add/modify thus: + if (riding) { + if (GET_MOVE(RIDING(ch)) < need_movement) { + send_to_char(ch, "Your mount is too exhausted.\r\n"); + return 0; + } + } else { ! if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { ! if (need_specials_check && ch->master) ! send_to_char(ch, "You are too exhausted to follow.\r\n"); ! else ! send_to_char(ch, "You are too exhausted.\r\n"); ! return 0; ! } ! } + + if (riding && GET_SKILL(ch, SKILL_RIDING) < rand_number(1, 101)-rand_number(-4,need_movement)) { + act("$N rears backwards, throwing you to the ground.", FALSE, ch, 0, RIDING(ch), TO_CHAR); + act("You rear backwards, throwing $n to the ground.", FALSE, ch, 0, RIDING(ch), TO_VICT); + act("$N rears backwards, throwing $n to the ground.", FALSE, ch, 0, RIDING(ch), TO_NOTVICT); + dismount_char(ch); + damage(ch, ch, dice(1,6), -1); + return 0; + } In do_simple_move modify the tunnel check as follows: + if ((riding || ridden_by) && IS_SET(ROOM_FLAGS(EXIT(ch, dir)->to_room), ROOM_TUNNEL)) { + send_to_char(ch, "There isn't enough room there, while mounted.\r\n"); + return 0; + } else { if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) && num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= tunnel_size) { if (tunnel_size > 1) send_to_char(ch, "There isn't enough room for you to go there!\r\n"); else send_to_char(ch, "There isn't enough room there for more than one person!\r\n"); return (0); } + } In do_simple_move, change the block which modifies movement points like so: /* Now we know we're allowed to go into the room. */ ! if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch) && !(riding || ridden_by)) GET_MOVE(ch) -= need_movement; + else if (riding) + GET_MOVE(RIDING(ch)) -= need_movement; + else if (ridden_by) + GET_MOVE(RIDDEN_BY(ch)) -= need_movement; In do_simple_move, change the small departure message code block to look like so: + if (riding) { + if (!IS_AFFECTED(RIDING(ch), AFF_SNEAK)) { + if (IS_AFFECTED(ch, AFF_SNEAK)) { + snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]); + act(buf2, TRUE, RIDING(ch), 0, 0, TO_ROOM); + } else { + snprintf(buf2, sizeof(buf2), "$n rides $N %s.", dirs[dir]); + act(buf2, TRUE, ch, 0, RIDING(ch), TO_NOTVICT); + } + } + } else if (ridden_by) { + if (!IS_AFFECTED(ch, AFF_SNEAK)) { + if (IS_AFFECTED(RIDDEN_BY(ch), AFF_SNEAK)) { + snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]); + act(buf2, TRUE, ch, 0, 0, TO_ROOM); + } else { + snprintf(buf2, sizeof(buf2), "$n rides $N %s.", dirs[dir]); + act(buf2, TRUE, RIDDEN_BY(ch), 0, ch, TO_NOTVICT); + } + } + } else if (!IS_AFFECTED(ch, AFF_SNEAK)) { + snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]); + act(buf2, TRUE, ch, 0, 0, TO_ROOM); + } In_do_simple_move, after the character is moved (and in the case of dg, the script is checked) add mount/ride movement and change the small arrival message code block to this: + if (riding && same_room && RIDING(ch)->in_room != ch->in_room) { + char_from_room(RIDING(ch)); + char_to_room(RIDING(ch), ch->in_room); + } else if (ridden_by && same_room && RIDDEN_BY(ch)->in_room != ch->in_room) { + char_from_room(RIDDEN_BY(ch)); + char_to_room(RIDDEN_BY(ch), ch->in_room); + } + + if (!IS_AFFECTED(ch, AFF_SNEAK)) { + if (riding && same_room && !IS_AFFECTED(RIDING(ch), AFF_SNEAK)) { + snprintf(buf2, sizeof(buf2), "$n arrives from %s%s, riding $N.", + ((dir == UP || dir == DOWN) ? "the " : ""), + (dir == UP ? "below": dir == DOWN ? "above" : dirs[rev_dir[dir]])); + act(buf2, TRUE, ch, 0, RIDING(ch), TO_ROOM); + } else if (ridden_by && same_room && !IS_AFFECTED(RIDDEN_BY(ch), AFF_SNEAK)) { + snprintf(buf2, sizeof(buf2), "$n arrives from %s%s, ridden by $N.", + ((dir == UP || dir == DOWN) ? "the " : ""), + (dir == UP ? "below": dir == DOWN ? "above" : dirs[rev_dir[dir]])); + act(buf2, TRUE, ch, 0, RIDDEN_BY(ch), TO_ROOM); + } else if (!riding || (riding && !same_room)) { + act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM); + } + } /* This changes stock behavior: it doesn't work with in/out/enter/exit as dirs */ In do_simple_move after the call to look_at_room, modify the DT if like so: + /* DT! (Hopefully these are rare in your MUD) -dak */ + if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH)) { + if (GET_LEVEL(ch) < LVL_IMMORT) { + log_death_trap(ch); + death_cry(ch); + extract_char(ch); + } + + if (riding && GET_LEVEL(RIDING(ch)) < LVL_IMMORT) { + log_death_trap(ch); + death_cry(ch); + extract_char(ch); + } + + if (ridden_by && GET_LEVEL(RIDDEN_BY(ch)) < LVL_IMMORT) { + log_death_trap(ch); + death_cry(ch); + extract_char(ch); + } + return (0); + } At the end of the file, add the following functions: /* Mounts (DAK) */ ACMD(do_mount) { char arg[MAX_INPUT_LENGTH]; struct char_data *vict; one_argument(argument, arg); if (!arg || !*arg) { send_to_char(ch, "Mount who?\r\n"); return; } else if (!(vict = get_char_room_vis(ch, arg, NULL))) { send_to_char(ch, "There is no-one by that name here.\r\n"); return; } else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_IMMORT) { send_to_char(ch, "Ehh... no.\r\n"); return; } else if (RIDING(ch) || RIDDEN_BY(ch)) { send_to_char(ch, "You are already mounted.\r\n"); return; } else if (RIDING(vict) || RIDDEN_BY(vict)) { send_to_char(ch, "It is already mounted.\r\n"); return; } else if (GET_LEVEL(ch) < LVL_IMMORT && IS_NPC(vict) && !MOB_FLAGGED(vict, MOB_MOUNTABLE)) { send_to_char(ch, "You can't mount that!\r\n"); return; } else if (!GET_SKILL(ch, SKILL_MOUNT)) { send_to_char(ch, "First you need to learn *how* to mount.\r\n"); return; } else if (GET_SKILL(ch, SKILL_MOUNT) <= rand_number(1, 101)) { act("You try to mount $N, but slip and fall off.", FALSE, ch, 0, vict, TO_CHAR); act("$n tries to mount you, but slips and falls off.", FALSE, ch, 0, vict, TO_VICT); act("$n tries to mount $N, but slips and falls off.", TRUE, ch, 0, vict, TO_NOTVICT); damage(ch, ch, dice(1, 2), -1); return; } act("You mount $N.", FALSE, ch, 0, vict, TO_CHAR); act("$n mounts you.", FALSE, ch, 0, vict, TO_VICT); act("$n mounts $N.", TRUE, ch, 0, vict, TO_NOTVICT); mount_char(ch, vict); if (IS_NPC(vict) && !AFF_FLAGGED(vict, AFF_TAMED) && GET_SKILL(ch, SKILL_MOUNT) <= rand_number(1, 101)) { act("$N suddenly bucks upwards, throwing you violently to the ground!", FALSE, ch, 0, vict, TO_CHAR); act("$n is thrown to the ground as $N violently bucks!", TRUE, ch, 0, vict, TO_NOTVICT); act("You buck violently and throw $n to the ground.", FALSE, ch, 0, vict, TO_VICT); dismount_char(ch); damage(vict, ch, dice(1,3), -1); } } ACMD(do_dismount) { if (!RIDING(ch)) { send_to_char(ch, "You aren't even riding anything.\r\n"); return; } else if (SECT(ch->in_room) == SECT_WATER_NOSWIM && !has_boat(ch)) { send_to_char(ch, "Yah, right, and then drown...\r\n"); return; } act("You dismount $N.", FALSE, ch, 0, RIDING(ch), TO_CHAR); act("$n dismounts from you.", FALSE, ch, 0, RIDING(ch), TO_VICT); act("$n dismounts $N.", TRUE, ch, 0, RIDING(ch), TO_NOTVICT); dismount_char(ch); } ACMD(do_buck) { if (!RIDDEN_BY(ch)) { send_to_char(ch, "You're not even being ridden!\r\n"); return; } else if (AFF_FLAGGED(ch, AFF_TAMED)) { send_to_char(ch, "But you're tamed!\r\n"); return; } act("You quickly buck, throwing $N to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_CHAR); act("$n quickly bucks, throwing you to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_VICT); act("$n quickly bucks, throwing $N to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_NOTVICT); GET_POS(RIDDEN_BY(ch)) = POS_SITTING; if (rand_number(0, 4)) { send_to_char(RIDDEN_BY(ch), "You hit the ground hard!\r\n"); damage(RIDDEN_BY(ch), RIDDEN_BY(ch), dice(2,4), -1); } dismount_char(ch); /* * you might want to call set_fighting() or some nonsense here if you * want the mount to attack the unseated rider or vice-versa. */ } ACMD(do_tame) { char arg[MAX_INPUT_LENGTH]; struct affected_type af; struct char_data *vict; one_argument(argument, arg); if (!arg || !*arg) { send_to_char(ch, "Tame who?\r\n"); return; } else if (!(vict = get_char_room_vis(ch, arg, NULL))) { send_to_char(ch, "They're not here.\r\n"); return; } else if (GET_LEVEL(ch) < LVL_IMMORT && IS_NPC(vict) && !MOB_FLAGGED(vict, MOB_MOUNTABLE)) { send_to_char(ch, "You can't do that to them.\r\n"); return; } else if (!GET_SKILL(ch, SKILL_TAME)) { send_to_char(ch, "You don't even know how to tame something.\r\n"); return; } else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_IMMORT) { send_to_char(ch, "You can't do that.\r\n"); return; } else if (GET_SKILL(ch, SKILL_TAME) <= rand_number(1, 101)) { send_to_char(ch, "You fail to tame it.\r\n"); return; } af.type = SKILL_TAME; af.duration = 24; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_TAMED; affect_join(vict, &af, FALSE, FALSE, FALSE, FALSE); act("You tame $N.", FALSE, ch, 0, vict, TO_CHAR); act("$n tames you.", FALSE, ch, 0, vict, TO_VICT); act("$n tames $N.", FALSE, ch, 0, vict, TO_NOTVICT); } END ACT.MOVEMENT.C BEGIN CLASS.C In void_init_spell_levels, right at the beginning before anything is assigned, add: + int i, j; + int cls_mage = (1 << CLASS_MAGIC_USER); + int cls_cleric = (1 << CLASS_CLERIC); + int cls_thief = (1 << CLASS_THIEF); + int cls_warrior = (1 << CLASS_WARRIOR); + + /* + * Assign a spell/skill to a a whole group of classes (0 is all) + * For instance, { SKILL_SECOND_ATTACK, cls_mage | cls_cleric, 14 }, + * will give mages and clerics the SECOND_ATTACK skill at level 14. + * More convenient than individual spell_level()s. Use 0 to give + * a skill to all the classes. + * -dkoepke + */ + int base_skl[][3] = { + { SKILL_MOUNT , 0, 1 }, + { SKILL_RIDING, 0, 1 }, + + { -1, -1 } /* THIS MUST END THE LIST */ + }; + + /* give all the base_skl[]'s */ + for (j = 0; base_skl[j][0] != -1; j++) + for (i = 0; i < NUM_CLASSES; i++) + if (!base_skl[j][1] || IS_SET(base_skl[j][1], (1 << i))) + spell_level(base_skl[j][0], i, base_skl[j][2]); + + /* + * in my base patch, cls_mage, etc. are unused and that leads to + * annyoing warnings, so here I'll use them... + */ + j = (cls_mage-cls_mage)+(cls_cleric-cls_cleric)+(cls_thief-cls_thief)+ + (cls_warrior-cls_warrior); In init_spell_levels, add the skill to whatever classes you want, like so: + spell_level(SKILL_TAME, CLASS_WARRIOR, 7); END CLASS.C BEGIN CONSTANTS.C In action_bits[], add this *before* DEAD (or wherever else you assign it in structs.h): + "MOUNTABLE", In affected_bits, add this in one of the unused slots (or wherever it is in structs.h): + "TAMED", END CONSTANTS.C BEGIN FIGHT.C In void damage, change the skill message code as follows: + if (attacktype != -1) { ! if (!IS_WEAPON(attacktype)) ! skill_message(dam, ch, victim, attacktype); ! else { ! if (GET_POS(victim) == POS_DEAD || dam == 0) { ! if (!skill_message(dam, ch, victim, attacktype)) ! dam_message(dam, ch, victim, attacktype); ! } else { ! dam_message(dam, ch, victim, attacktype); ! } ! } + } END FIGHT.C BEGIN HANDLER.C At the top, where local functions are prototyped, add: + void dismount_char(struct char_data *ch); + void mount_char(struct char_data *ch, struct char_data *mount); In extract_char_final after followers are handled, add: + if (RIDING(ch) || RIDDEN_BY(ch)) + dismount_char(ch); At the end of the file, add the following functions: +/* dismount_char() / fr: Daniel Koepke (dkoepke@california.com) + * If a character is mounted on something, we dismount them. If + * someone is mounting our character, then we dismount that someone. + * This is used for cleaning up after a mount is cancelled by + * something (either intentionally or by death, etc.) + */ +void dismount_char(struct char_data *ch) +{ + if (RIDING(ch)) { + RIDDEN_BY(RIDING(ch)) = NULL; + RIDING(ch) = NULL; + } + + if (RIDDEN_BY(ch)) { + RIDING(RIDDEN_BY(ch)) = NULL; + RIDDEN_BY(ch) = NULL; + } +} + +/* mount_char() / fr: Daniel Koepke (dkoepke@california.com) + * Sets _ch_ to mounting _mount_. This does not make any checks + * what-so-ever to see if the _mount_ is mountable, etc. That is + * left up to the calling function. This does not present any + * messages, either. + */ +void mount_char(struct char_data *ch, struct char_data *mount) +{ + RIDING(ch) = mount; + RIDDEN_BY(mount) = ch; +} END HANDLER.C BEGIN INTERPRETER.C Where ACMDs are defined, add: +ACMD(do_buck); +ACMD(do_dismount); +ACMD(do_mount); +ACMD(do_tame); In the command table, add: + { "buck" , POS_STANDING, do_buck , 0, 0 }, + { "dismount" , POS_STANDING, do_dismount , 0, 0 }, + { "mount" , POS_STANDING, do_mount , 0, 0 }, + { "tame" , POS_STANDING, do_tame , 0, 0 }, END INTERPRETER.C BEGIN SPELL_PARSER.C Where the skills are, at the bottom of the file, add in: + skillo(SKILL_MOUNT, "mount"); + skillo(SKILL_RIDING, "track"); + skillo(SKILL_TAME, "tame"); END SPELL_PARSER.C BEGIN SPELLS.H Where all the skill numbers are defined, add in: +#define SKILL_MOUNT 141 /* (R) Mounting (DAK) */ +#define SKILL_RIDING 142 /* (R) Riding (DAK) */ +#define SKILL_TAME 143 /* (R) Ability to tame (DAK) */ END SPELLS.H BEGIN STRUCTS.H In mobile flags, define MOB_MOUNTABLE appropriately: +#define MOB_MOUNTABLE (1 << 18) /* Mob may be mounted for riding */ In affect bits, define AFF_TAMED appropriately: +#define AFF_TAMED (1 << 16) /* (R) Char has been tamed */ In struct char_special_data, add: + struct char_data *riding; /* Who are they riding? (DAK) */ + struct char_data *ridden_by; /* Who is riding them? (DAK) */ END STRUCTS.H BEGIN UTILS.H Add the macros for RIDING and RIDDEN_BY: +#define RIDING(ch) ((ch)->char_specials.riding) /* (DAK) */ +#define RIDDEN_BY(ch) ((ch)->char_specials.ridden_by) /* (DAK) */ END UTILS.H END MOUNT CODE WALKTHROUGH *** The original text of the readme from the dak mount system patch is below: `_.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._' Mount Patch Copyright 1996, by Daniel Koepke `_.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._.,-'~'-,._' I. Introduction =============== Here's my silly little mount patch as promised. The implemented mount system is rather primitive, but I hope you like it and can find some good use for it. There are three new skills which are added with this patch, MOUNT which determines whether you can mount or not, RIDING for determining how well you can ride, and TAME for taming animals so that they do not run away, etc. There are some utility changes about the code made by this patch. I realize that is a poor way to do things and could make it more difficult for you to patch other things, but it was somewhat neccessary. I don't believe any of the small changes are large enough to cause rejects in other patches, though. II. Standard (Keep-me-from-court) Disclaimer ============================================ Use this at your own risks. There is (like pretty much all code) some bugs. That is to be expected. I am giving you this, so I expect that, in return, you will send me improvements you add, or report any bugs you encounter. My e-mail address is dkoepke@california.com. You do not need to give me credit for this. I ask, though, that you do not take credit for it. I appreciate any credit you give me. Of course, you have to follow the CircleMUD license... but that goes without saying and you are *obviously* already doing that [pssst, read doc/license.doc if you haven't, yet]. III. Installing =============== Okay, now on to how to install this thing... Move the mount.diff file to the src/ directory. Go into the src/ directory and type: % patch < mount.diff If you get any failures/rejects, look at the .rej files and manually install from that (key: '+' is add, '-' is remove, '!' is change). If the entire thing fails, manually patch from the mount.diff file (same key). IV. For the Coders ================== Here's some basics about how mounts work: MACRO: RIDING(ch), ch->char_specials.riding Returns who is being mounting by the character or NULL if no-one MACRO: RIDDEN_BY(ch), ch->char_specials.ridden_by Returns who is mounted on the character or NULL if no-one FLAG: MOB_MOUNTABLE, MOB_x (1 << 18) Should be set on any mobile that can be mounted FLAG: AFF_TAMED, AFF_x (1 << 16) Set by do_tame() when the character is tamed FUNCTIONS: do_mount, do_dismount, do_buck, bottom of act.movement.c Player-level interface for mounting and dismounting, and buck is for removing a mounted player from you. All of these are ACMDs. FUNCTIONS: do_tame(), last function in act.movement.c Tames a character for easier mounting, or whatnot. FUNCTION: mount_char(ch,vict), bottom of handler.c Makes _ch_ mount _vict_ FUNCTION: dismount_char(ch) Sets up so that player is not mounting or being mounted SKILL: SKILL_MOUNT, SKILL_x (141) The skill to determine how well they are at mounting (see: do_mount) SKILL: SKILL_RIDING, SKILL_x (142) The skill to determine how well they ride (see: do_simple_move) SKILL: SKILL_TAME, SKILL_x (143) The skill to determine if and how well they can tame (see: do_tame) V. Other Patches By Me ====================== The below are availible at the CircleMUD anonymous ftp site (see below for the address): Filename: new.do_who.diff.gz, /pub/CircleMUD/contrib/code Usage : A replacement for do_who(), it splits apart immortals and mortals, gives immortals a "who title" ("Immortal" instead of "31 War"), keeps a count of highest players on per boot, and a little bit more. Filename: multi_hit.diff.gz, /pub/CircleMUD/contrib/code Usage : Adds multiple attacks per round and the connected skills. Filename: obj_mail.diff.gz, /pub/CircleMUD/contrib/code Usage : Permits attaching of objects to mail Filename: new_prompt.diff.gz, /pub/CircleMUD/contrib/code Usage : Enhanced prompt code that interprets a character's prompt. Note that this will change your pfile... Filename: query_ansi.diff.gz, /pub/CircleMUD/contrib/code Usage : A patch to query a logging in user for whether they want ANSI color support on/off before display of the title screen. Actually quite useful... VI. Popular CircleMUD Sites =========================== Anonymous ftp : [ftp.circlemud.org] Homepage : [http://www.circlemud.org/] Code snippets : [http://cspo.queensu.ca/~fletcher/Circle/Snippet/] Have fun and godspeed, -- Daniel Koepke dkoepke@california.com Forgive me father, for I am sin. *** Mike Sulmiki had a few comments in his fixed mount code patch: I fixed the ch references in ACMD(do_buck) so that the rider gets hurt when he gets thrown off instead of the mount, and fixed a small bug which made the "$n has arrived message" show up twice when they were riding. -- Mike Sulmicki of Axxenfall (sulmicki.erols.com 4000)