Here's my version of formation fighting. Basically, it puts players into a formation of 3 rows, 3 people per row. On my mud, I have a max of 9 people in a group, so it works well for that. ------------------------- | 0 | 1 | 2 | ------------------------- | 3 | 4 | 5 | ------------------------- | 6 | 7 | 8 | ------------------------- Above is the basic layout of the formation. The leader of the group has control for positioning people. This is a VERY basic formation fighting, and yields no bonuses or whatever for players in different positions. In my mud, mobs will attack anyone in the group fighting them instead of only focusing on one person. The middle row is as normal, while the front row gets a bonus to +hit and a reduction on effectively casting offensive spells; the back row gets a reduction to +hit and a bonus on effectively casting offensive spells (would be kinda difficult to concentrate on casting spells while in the front row fending for your life with a sword/axe/butterknife/etc eh?) The front row will also take the brunt of the damage, while the middle row a little less, and the back row even less than that. After putting form fighting in, you can decide how you want your mobs to act in that regard. This is not a patch because I hate patches, and if I made one from my mud, it probably wouldn't patch in cleanly anyways, so do it like you should and patch it by hand. ======================================================================================= ==================== structs.h ==================== before: struct char_special_data { add: #define MAX_FORM_POSITIONS 9 /* Lars - 02/00 */ -------------------- after: int timer; /* timer for update */ add: int form_pos; /* formation position */ int form_total[MAX_FORM_POSITIONS]; /* formation status (leader) */ ==================== utils.h ==================== after: #define SECS_PER_REAL_YEAR (365*SECS_PER_REAL_DAY) add: /* Formation Fighting - Lars 02/00 */ #define GET_FORM_POS(ch) ((ch)->char_specials.form_pos) #define GET_FORM_TOTAL(ch, i) ((ch)->char_specials.form_total[i]) ==================== act.other.c ==================== after: ACMD(do_gen_tog); add: ACMD(do_form); ACMD(do_reform); int find_form_pos(struct char_data *ch); -------------------- after the func: void print_group(struct char_data *ch) add the func and commands: ACMD(do_form) /* Lars - 02/00 */ { struct char_data *k; struct follow_type *f; int i, counter = 0, found = FALSE; /* Are we grouped? */ if (!AFF_FLAGGED(ch, AFF_GROUP)) send_to_char("But you are not a member of any group!\r\n", ch); else { /* yes we are */ send_to_char("Positions:\r\n", ch); k = (ch->master ? ch->master : ch); /* * error checking * * This has been commented out, but left in the event you have problems * getting this to work. These checks will print out all formation positions, * and their values (taken or free). It will also print the total number * of members in the group. */ /* for (i = 0; i < MAX_FORM_POSITIONS; i++) { j = 0; if (GET_FORM_TOTAL(k, i) > 0) j++; sprintf(buf, "Pos: %d, Value: %d\r\n", i, j); send_to_char(buf, k); } */ /* print the leaders position */ /* if (AFF_FLAGGED(k, AFF_GROUP)) { sprintf(buf, "Pos %d: $N", GET_FORM_POS(k)); act(buf, FALSE, ch, 0, k, TO_CHAR); } */ /* now print followers positions */ /* for (f = k->followers; f; f = f->next) { if (!AFF_FLAGGED(f->follower, AFF_GROUP)) continue; sprintf(buf, "Pos %d: $N", GET_FORM_POS(f->follower)); act(buf, FALSE, ch, 0, f->follower, TO_CHAR); } */ send_to_char("Formation:\r\n", ch); /* format the output */ for (i = 0; i < MAX_FORM_POSITIONS; i++) { /* loop through total form positions */ if (GET_FORM_POS(k) == i) { /* lets check for the leader first */ sprintf(buf, "[%-25s] ", GET_NAME(k)); /* found, spit out the output */ send_to_char(buf, ch); if (counter >= 2) { /* checks if this is the 3rd entry on a line */ send_to_char("\r\n", ch); counter = 0; } else counter++; /* it's not, increment */ } else { for (f = k->followers; f; f = f->next) { /* onto the followers */ if (GET_FORM_POS(f->follower) == i) { /* are you the one? */ sprintf(buf, "[%-25s] ", GET_NAME(f->follower)); /* yes, send your name */ send_to_char(buf, ch); found = TRUE; } } if (!found) send_to_char("[ ] ", ch); /* empty brackets to format menu logically if no one is found */ if (counter >= 2) { /* more checking for rows */ send_to_char("\r\n", ch); counter = 0; } else counter++; /* increment */ } found = FALSE; } } } ACMD(do_reform) { struct char_data *vict; int j, i; two_arguments(argument, buf, buf2); if (!*buf) { send_to_char("Whom do you wish to reform?\r\n", ch); return; } if (ch->master) { send_to_char("You have to lead the group to reform members.\r\n", ch); return; } if (!(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM))) { send_to_char(NOPERSON, ch); return; } if ((vict->master != ch) && (vict != ch)) { send_to_char("That person is not in your group.\r\n", ch); return; } if (!AFF_FLAGGED(ch, AFF_GROUP)) { send_to_char("That person is not in your group.\r\n", ch); return; } if (!*buf2) { send_to_char("Reform to which position?\r\n", ch); return; } j = atoi(buf2); if (j > MAX_FORM_POSITIONS || j < 0) { send_to_char("That is not a valid position.\r\n", ch); return; } if (GET_FORM_TOTAL(ch, j) > 0) { /* need to replace with current position holder */ send_to_char("That position is already taken.\r\n", ch); return; } else { for (i = 0; i < MAX_FORM_POSITIONS; i++) { /* find the old position */ if (GET_FORM_POS(vict) == i) /* is this it? */ GET_FORM_TOTAL(ch, i) = 0; /* set the old position in the array to 0 */ } GET_FORM_POS(vict) = j; /* give them the new position */ GET_FORM_TOTAL(ch, j) = 1; /* update the array */ sprintf(buf, "$N has been reformed to position %d.\r\n", j); act(buf, FALSE, ch, 0, vict, TO_CHAR); send_to_char("You have been reformed.\r\n", vict); return; } } int find_form_pos(struct char_data *ch) { int i; for (i = 0; i < MAX_FORM_POSITIONS; i++) { if (GET_FORM_TOTAL(ch, i) > 0) /* occupied? */ continue; else { GET_FORM_TOTAL(ch, i) = 1; /* position is free, take it! */ return (i); } } return (0); /* if all else fails, should never get here */ } =================== fight.c - this isn't necessarily a part of formation fighting, but it allows the opponent to attack, randomly, other members in the group fighting it. This works exceptionally well if you have multiple attacks per round. =================== after: int compute_thaco(struct char_data *ch, struct char_data *vict); add: void find_victim(struct char_data *ch); ------------------- before (in perform_violence(void)): hit(ch, FIGHTING(ch), TYPE_UNDEFINED) add: find_victim(ch); ------------------- after the func perform_violence add: /* used to determine who, in a group will be attacked */ void find_victim(struct char_data *ch) { struct char_data *k; struct follow_type *f; int num_members = 1, attack = 1, counter = 2; if (GET_POS(ch) < POS_FIGHTING) { stop_fighting(ch); return; } k = (FIGHTING(ch)->master ? FIGHTING(ch)->master : FIGHTING(ch)); /* find the number of members in the group */ for (f = k->followers; f; f = f->next) num_members += 1; /* figure out which one is to be attacked */ attack = number(1, num_members); /* victim is the leader of the group */ if (attack == 1) { FIGHTING(ch) = k; return; } else { /* victim is one of the leaders followers */ for (f = k->followers; f; f = f->next) { if (IN_ROOM(FIGHTING(ch)) != IN_ROOM(f->follower)) counter += 1; else if (counter != attack) counter += 1; else { FIGHTING(ch) = f->follower; return; } } } log("SYSERR: find_victim reached end of loop without finding a victim"); return; } ======================================================================================= I don't require anything for the use of this, but it would be nice to get a note saying that you liked/hated it, maybe a line in the credits, and monetary donations are, of course, always accepted ;) If this breaks you, destroys anything, it's not my doing. It works wonderfully for me. Have fun! lars@temperedweaves.com