This will add in player settable colors, so player 1 can speak with black and red to other people, but player 2 can speak in green and light green and the other people see it. This may lag the server if its slow, but I haven't had any color-slowness problems; in my opinion this adds lots of variety and uniqueness. Credits to Thomas Arp for lots of help, Peter Ajamian for help, and Ben Merton for the original concept. If you wish to make it so everyone can set colors but they only see what they have set, its easy to change that, contact me if you wish that. Example of how to expand: We now want something like holler expandable, add on a #define COLOR_HOLLER 7 and up the NUM_COLORS to 8. Then whenever you see a str_dup("nnnnnnn"); add on an extra n. If you use binary pfiles, you will need pwipe each time you change this. Now in act.other add on a field for holler, and have COLOR_HOLLER next to it. Now, when you actually go into where holler is done, tack on some of the things like in do_say... all done. -Edward Felch lord.spinlock.net 9991 Darkness Falling MUD Assumptions: - ascii pfiles - already have it so you can use & to put color in like say &rhello. - that you want a unique way of handling colors for players structs.h Near the other defines add in: /* player definable colors */ #define COLOR_SAY1 0 #define COLOR_SAY2 1 #define COLOR_PROMPT 2 #define COLOR_TELL 3 #define COLOR_GOSSIP 4 #define COLOR_OBJECT 5 #define COLOR_CREATURE 6 #define NUM_COLORS 7 In: struct char_player_data { add char *player_color; // defined colors Later on in: struct char_file_u { add char player_color[NUM_COLORS+1]; utils.h Somewhere add in: #define GET_PLAYER_COLOR(ch) ((ch)->player.player_color) In act.other.c or somewhere nice: struct set_fields { const char *change_field; int field; } set_pcolor_fields[] = { { "say1", COLOR_SAY1}, { "say2", COLOR_SAY2}, { "tell", COLOR_TELL}, { "gossip", COLOR_GOSSIP}, { "object", COLOR_OBJECT}, { "creature", COLOR_CREATURE}, { "\n", -1} }; const char *color_char[][2] = { { "red", "r"}, { "blue", "b"}, { "green", "g"}, { "yellow", "y"}, { "magneta", "m"}, { "grey", "w"}, { "cyan", "c"}, { "bred", "R"}, { "bblue", "B"}, { "bgreen", "G"}, { "byellow", "Y"}, { "bmagneta", "M"}, { "bcyan", "C"}, { "white", "W"}, { "black", "D"}, { "normal", "n"}, { "\n", "\n"} }; ACMD(do_setcolor) { char field[MAX_INPUT_LENGTH], ccolor[MAX_INPUT_LENGTH]; int mode = 0, len = 0, found = 0, cmode = 0; int change = 0; half_chop(argument, field, ccolor); if (!field || !*field) { send_to_char("You can change the following fields:\r\n", ch); for (mode = 0; *(set_pcolor_fields[mode].change_field) != '\n'; mode++) { sprintf(buf, " %s\r\n", set_pcolor_fields[mode].change_field); send_to_char(buf, ch); } return; } /* go through settable_colors */ len = strlen(field); for (mode = 0; *(set_pcolor_fields[mode].change_field) != '\n' || found; mode++) if (is_abbrev(field, set_pcolor_fields[mode].change_field)) { found = 1; break; } if (!found) { send_to_char("You cannot change that field's color!\r\n", ch); return; } if (!ccolor || !*ccolor) { send_to_char("You can use the following color codes:\r\n", ch); for (cmode = 0; *(color_char[cmode][0]) != '\n'; cmode++) { sprintf(buf, " &%s%s\r\n", color_char[cmode][1], color_char[cmode][0]); send_to_char(buf, ch); } return; } found = 0; len = strlen(ccolor); for (cmode = 0; *(color_char[cmode][0]) != '\n' || found; cmode++) if (is_abbrev(ccolor, color_char[cmode][0])) { found = 1; break; } if (!found) { send_to_char("What color did you want that to be?\r\n", ch); return; } /* we have a correct field, and a color */ change = set_pcolor_fields[mode].field; GET_PLAYER_COLOR(ch)[change] = *(color_char[cmode][1]); sprintf(buf, "You have changed %s to be %s.\r\n", set_pcolor_fields[mode].change_field, color_char[cmode][0]); send_to_char(buf, ch); return; } In db.c: in load_char where everything is being set to default values: GET_PLAYER_COLOR(ch) = str_dup("nnnnnnn"); in load_char in the actual setting of variables, under P add: else if (!strcmp(tag, "Pcol")) GET_PLAYER_COLOR(ch) = str_dup(line); in save_char in the saving of variables, add in somewhere: if (GET_PLAYER_COLOR(ch)) fbprintf(fl, "Pcol: %s\n", GET_PLAYER_COLOR(ch)); in init_char add in: GET_PLAYER_COLOR(ch) = str_dup("nnnnnnn"); in parse_mobile where things like title and name are being NULLED add in: mob_proto[i].player.player_color = str_dup("nnnnnnn"); in free_char you should probably add in: if (GET_PLAYER_COLOR(ch)) free(GET_PLAYER_COLOR(ch)); In medit.c inside of void init_mobile(struct char_data *mob) add in GET_PLAYER_COLOR(mob) = str_dup("nnnnnnn"); In hander.c add in: const char *interpret_color(struct char_data *ch, int position) { char return_s[MAX_INPUT_LENGTH]; char *returner; sprintf(return_s, "&%c", GET_PLAYER_COLOR(ch)[position]); returner = str_dup(return_s); return returner; } In handler.h add in under utility: const char *interpret_color(struct char_data *ch, int position); For this implementation of unique, definable colors I will only show you one place where it is declared, which uses say1 and say2: Inside of act.comm.c: ACMD(do_say) { skip_spaces(&argument); if (!*argument) send_to_char("Yes, but WHAT do you want to say?\r\n", ch); else { delete_doubledollar(argument); sprintf(buf, "%s$n says, &n'%s%s&n'&n", interpret_color(ch, COLOR_SAY1), interpret_color(ch, COLOR_SAY2), argument); act(buf, FALSE, ch, 0, 0, TO_ROOM|DG_NO_TRIG); // if you dont use dgscripts, remove the |DG_NO_TRIG if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT)) send_to_char(OK, ch); else { delete_doubledollar(argument); sprintf(buf, "%sYou say, &n'%s%s&n'&n\r\n", interpret_color(ch, COLOR_SAY1), interpret_color(ch, COLOR_SAY2), argument); send_to_char(buf, ch); } } /* trigger check */ speech_mtrigger(ch, argument); // if you use dgscripts speech_wtrigger(ch, argument); // if you use dgscripts }