/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * _/ _/ * * _/_/_/ _/_/ _/_/_/ _/ _/_/ _/ _/ _/_/_/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/_/_/ _/ _/_/ _/_/_/ _/_/_/ * *************************************************************************** * Mindcloud Copyright 2001-2003 by Jeff Boschee (Zarius), * * Additional credits are in the help file CODECREDITS * * All Rights Reserved. * ***************************************************************************/ /* * Communication storage system. Ye Jobo. */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <ctype.h> #include "merc.h" HISTORY_DATA *history_free; HISTORY_DATA *stored_tells; void init_channel_storage() { int i, j; for (i = 1; i < STORE_MAX; i++) { for (j = 1; j <= MAX_STORAGE; j++) { old_messages[i].last[j] = str_dup(""); } } } void update_channel_storage(char *buf, int chan) { char xbuf[MAX_STRING_LENGTH]; char tbuf[20]; int i; if (chan != STORE_TELL) { xprintf(tbuf, "%-18.18s", buf); xprintf(xbuf, "%s %s", tbuf, line_indent(&buf[19], 15, 85)); } else xprintf(xbuf, buf); if (chan >= STORE_MAX) { bug("update_channel_storage : Bad channel", 0); return; } for (i = MAX_STORAGE; i > 1; i--) { free_string(old_messages[chan].last[i]); old_messages[chan].last[i] = str_dup(old_messages[chan].last[i - 1]); } free_string(old_messages[chan].last[1]); old_messages[chan].last[1] = str_dup(xbuf); } void do_lastmessage(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; one_argument(argument, arg); if (IS_NPC(ch)) return; if (!str_cmp(arg, "chat")) showchannel(ch, STORE_CHAT); else if (!str_cmp(arg, "newbie")) showchannel(ch, STORE_NEWBIE); else if (!str_cmp(arg, "flame")) showchannel(ch, STORE_FLAME); else if (!str_cmp(arg, "roleplay")) showchannel(ch, STORE_ROLEPLAY); else if (!str_cmp(arg, "tell") && ch->level > 6) showchannel(ch, STORE_TELL); else if (ch->level < 7) send_to_char ("Show the last chat/newbie/flame/roleplay messages ?\n\r", ch); else send_to_char ("Show the last chat/newbie/flame/roleplay/tell messages ?\n\r", ch); return; } void showchannel(CHAR_DATA * ch, int chan) { char buf[MAX_STRING_LENGTH]; int i; for (i = MAX_STORAGE; i > 0; i--) { if (strlen(old_messages[chan].last[i]) < 1) continue; xprintf(buf, "%s\n\r", old_messages[chan].last[i]); send_to_char(buf, ch); } } void init_tell_storage() { HISTORY_DATA *history_new; HISTORY_DATA *history_prev = NULL; int i; for (i = 0; i < MAX_STORAGE; i++) { if (history_free == NULL) { history_new = alloc_perm(sizeof(*history_new)); } else { history_new = history_free; history_free = history_free->next; } history_new->message = str_dup(""); history_new->next = history_prev; history_prev = history_new; } stored_tells = history_new; } char *makedrunk(char *string, CHAR_DATA * ch) { /* This structure defines all changes for a character */ struct struckdrunk drunk[] = { {3, 10, {"a", "a", "a", "A", "aa", "ah", "Ah", "ao", "aw", "oa", "ahhhh"}}, {8, 5, {"b", "b", "b", "B", "B", "vb"}}, {3, 5, {"c", "c", "C", "cj", "sj", "zj"}}, {5, 2, {"d", "d", "D"}}, {3, 3, {"e", "e", "eh", "E"}}, {4, 5, {"f", "f", "ff", "fff", "fFf", "F"}}, {8, 2, {"g", "g", "G"}}, {9, 6, {"h", "h", "hh", "hhh", "Hhh", "HhH", "H"}}, {7, 6, {"i", "i", "Iii", "ii", "iI", "Ii", "I"}}, {9, 5, {"j", "j", "jj", "Jj", "jJ", "J"}}, {7, 2, {"k", "k", "K"}}, {3, 2, {"l", "l", "L"}}, {5, 8, {"m", "m", "mm", "mmm", "mmmm", "mmmmm", "MmM", "mM", "M"}}, {6, 6, {"n", "n", "nn", "Nn", "nnn", "nNn", "N"}}, {3, 6, {"o", "o", "ooo", "ao", "aOoo", "Ooo", "ooOo"}}, {3, 2, {"p", "p", "P"}}, {5, 5, {"q", "q", "Q", "ku", "ququ", "kukeleku"}}, {4, 2, {"r", "r", "R"}}, {2, 5, {"s", "ss", "zzZzssZ", "ZSssS", "sSzzsss", "sSss"}}, {5, 2, {"t", "t", "T"}}, {3, 6, {"u", "u", "uh", "Uh", "Uhuhhuh", "uhU", "uhhu"}}, {4, 2, {"v", "v", "V"}}, {4, 2, {"w", "w", "W"}}, {5, 6, {"x", "x", "X", "ks", "iks", "kz", "xz"}}, {3, 2, {"y", "y", "Y"}}, {2, 9, {"z", "z", "ZzzZz", "Zzz", "Zsszzsz", "szz", "sZZz", "ZSz", "zZ", "Z"}} }; char buf[MSL]; char temp; int pos = 0; int drunklevel; int randomnum; /* * Check how drunk a person is... */ if (ch == NULL) drunklevel = 5; else if (IS_NPC(ch)) drunklevel = 0; else drunklevel = ch->pcdata->condition[COND_DRUNK]; if (drunklevel > 0) { do { temp = toupper(*string); if ((temp >= 'A') && (temp <= 'Z')) { if (drunklevel > drunk[temp - 'A'].min_drunk_level) { randomnum = number_range(0, drunk[temp - 'A']. number_of_rep); strcpy(&buf[pos], drunk[temp - 'A']. replacement[randomnum]); pos += strlen(drunk[temp - 'A']. replacement[randomnum]); } else buf[pos++] = *string; } else { if ((temp >= '0') && (temp <= '9')) { temp = '0' + number_range(0, 9); buf[pos++] = temp; } else buf[pos++] = *string; } } while (*string++); buf[pos] = '\0'; /* Mark end of the string... */ strcpy(string, buf); return (string); } return (string); } void talk_channel(CHAR_DATA * ch, char *argument, int channel, int sub_channel, const char *verb) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if (RTIMER(ch->in_room, RTIMER_SILENCE) != 0) { send_to_char ("Something prevents you from speaking in this room.\n\r", ch); return; } if (argument[0] == '\0') { xprintf(buf, "%s what?\n\r", verb); buf[0] = UPPER(buf[0]); send_to_char(buf, ch); return; } if (IS_HEAD(ch, LOST_TONGUE)) { xprintf(buf, "You can't %s without a tongue!\n\r", verb); send_to_char(buf, ch); return; } if (IS_EXTRA(ch, GAGGED)) { xprintf(buf, "You can't %s with a gag on!\n\r", verb); send_to_char(buf, ch); return; } //if (IS_POLYAFF(ch, POLY_ZULOFORM)) // argument = darktongue(ch, argument); // if (ch->pcdata->condition[COND_DRUNK] > 10) // argument = makedrunk(argument, ch); if (IS_SPEAKING(ch, DIA_OLDE)) argument = oldelang(ch, argument); else if (IS_SPEAKING(ch, DIA_BAD)) argument = badlang(ch, argument); //argument = makedrunk ( argument, ch ); //if (channel == CHANNEL_CHAT) //mud_message(ch, argument); REMOVE_BIT(ch->deaf, channel); switch (channel) { default: if (ch->flag4 == 1) { xprintf(buf, "#nYou whine '#R%s#n'.\n\r", argument); send_to_char(buf, ch); xprintf(buf, "#n%s #Pwhines#n '#R$t#n'.", ch->name); } else if (channel == CHANNEL_FLAME) { xprintf(buf, "#nYou %s '#W%s#n'.\n\r", verb, argument); send_to_char(buf, ch); xprintf(buf, "#n%s %ses '#W$t#n'.", ch->name, verb); } else if (channel == CHANNEL_CHAT) { //argument = pcolor(ch, argument, 0); xprintf(buf, "#nYou %s '#R%s#n'.\n\r", verb, argument); send_to_char(buf, ch); if (ch->trust > 6) xprintf(buf, "#Y(#G*#Y)#C%s#Y(#G*#Y)#n '#1$t#n'.", ch->name); else if (IS_NPC(ch)) xprintf(buf, "%s chats '#R$t#n'.", ch->short_descr); else if (IS_CLASS(ch, CLASS_WEREWOLF)) xprintf(buf, "%s barks '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_MAGE)) xprintf(buf, "%s chants '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_SHAPESHIFTER)) xprintf(buf, "%s whispers '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_VAMPIRE)) xprintf(buf, "%s snarls '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_DRONE)) xprintf(buf, "%s drools '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_ANGEL)) xprintf(buf, "%s preaches '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_TANARRI)) xprintf(buf, "%s booms '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_LICH)) xprintf(buf, "%s squicks '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_HOBBIT)) xprintf(buf, "%s burps '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_DEMON)) xprintf(buf, "%s growls '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_CYBORG)) xprintf(buf, "%s chitters '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_GIANT)) xprintf(buf, "%s rumbles '#R$t#n'.", ch->name); else if (IS_CLASS(ch, CLASS_SKYBLADE)) xprintf(buf, "%s hollars '#R$t#n'.", ch->name); else xprintf(buf, "%s %ss '#R$t#n'.", ch->name, verb); } else { xprintf(buf, "You %s '#R%s#n'.\n\r", verb, argument); send_to_char(buf, ch); xprintf(buf, "%s %ss '#R$t#n'.", ch->name, verb); } break; case CHANNEL_IMMTALK: xprintf(buf, "#Y.:#P%s#Y:.#C $t.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CHANNEL_CLASS: switch (sub_channel) { case CC_ANGEL: xprintf(buf, "#0[#7%s#0]#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_DEMON: xprintf(buf, "#0[#R%s#0]#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_MAGE: xprintf(buf, "#n{{#0%s#n}}#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_SHIFTER: xprintf(buf, "#G*#C(>#R%s#C<)#G* #C'$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_CYBORG: xprintf(buf, "#p{#0-#p}#0%s#p{#0-#p} #C'$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_WW: xprintf(buf, "#Y((#L%s#Y))#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_NINJA: xprintf(buf, "#Y-*(#0%s#Y)*-#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_SAMURAI: xprintf(buf, "#C-=#R%s#C=- '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_KNIGHT: xprintf(buf, "#0.x.#7%s#0.x.#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_FAE: xprintf(buf, "#G>>#R(#Y%s#R)#G<<#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_GIANT: xprintf(buf, "#G<:>#o%s#G<:>#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_HOBBIT: xprintf(buf, "#o(#c*#o)#R%s#o(#c*#o)#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_TANARRI: xprintf(buf, "#Y{#R%s#Y}#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_LICH: xprintf(buf, "#G>*<#7%s#G>*<#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_DRONE: xprintf(buf, "#G<#0=#Y{#0%s#Y}#0=#G> #C'$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_SKYBLADE: xprintf(buf, "#B=#R*#w>#0%s#w<#R*#B= #W'$t#W'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_DROW: xprintf(buf, "#P.o0#0%s#P0o.#C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_MONK: xprintf(buf, "#0.x[#l%s#0]x. #C '$t'.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_VAMPIRE: xprintf(buf, "#R<<#0%s#R>>#C $t.#n", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CC_ZOMBIE: xprintf(buf, "#R[#y%s#R]#C $t.#n", ch->name); act (buf, ch, argument, NULL, TO_CHAR); break; case CC_DRAGON: { if (IS_CLASS(ch, CLASS_DRAGON)) { xprintf(buf, "#R[#y%s#R] #L'#7$t#L'", ch->name); act (buf, ch, argument, NULL, TO_CHAR); break; } else if (IS_CLASS(ch, CLASS_DRAGON) && IS_POLYAFF(ch, POLY_DRAGON)) { xprintf(buf, "#R:=#n %s #R=: #L'#7$t#L'", ch->morph); act (buf, ch, argument, NULL, TO_CHAR); break; } } } break; case CHANNEL_ROLEPLAY: xprintf(buf, "#o(#R%s#o) #n'#Y$t#n'.", ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CHANNEL_RELIGION: xprintf(buf, religion_table[ch->pcdata->religion].channel, ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; case CHANNEL_KINGDOM: xprintf(buf, "#n%s#n: #P%s #n '#7$t#n'.#n", kingdom_table[ch->pcdata->kingdom].whoname, ch->name); act(buf, ch, argument, NULL, TO_CHAR); break; } /* * silenced, and they don't know it :) */ if (!IS_NPC(ch) && IS_SET(ch->act, PLR_SILENCE)) return; /* * anti spamming */ //if (!IS_NPC(ch) && (channel == CHANNEL_CHAT || channel == CHANNEL_NEWBIE)) //{ // if (!str_cmp(ch->pcdata->last_global, argument)) return; // free_string(ch->pcdata->last_global); // ch->pcdata->last_global = str_dup(argument); //} for (d = descriptor_list; d != NULL; d = d->next) { CHAR_DATA *gch; if (d->connected != CON_PLAYING) continue; if ((gch = d->character) == NULL) continue; if (gch == ch) continue; if (IS_SET(gch->deaf, channel)) continue; if (channel == CHANNEL_IMMTALK && !IS_IMMORTAL(gch)) continue; if (channel == CHANNEL_CLASS && !IS_IMMORTAL(gch) && (gch->class != ch->class || gch->level < 3)) continue; if (channel == CHANNEL_RELIGION && !IS_IMMORTAL(gch) && gch->pcdata->religion != ch->pcdata->religion) continue; if ( channel == CHANNEL_KINGDOM && (!IS_NPC(gch) && gch->pcdata->kingdom != ch->pcdata->kingdom && !IS_IMMORTAL(gch))) continue; if (channel == CHANNEL_YELL && gch->in_room && gch->in_room->area != ch->in_room->area) continue; if (!IS_NPC(gch) && !IS_NPC(ch)) { bool ignore = FALSE; int i; for (i = 0; i < MAX_IGNORE; i++) if (gch->pcdata->ignore[i] == ch->pcdata->playerid) ignore = TRUE; if (ignore) continue; } act(buf, ch, argument, gch, TO_VICT); } return; } HISTORY_DATA *generate_history() { HISTORY_DATA *history_new; HISTORY_DATA *history_prev = NULL; int i; for (i = 0; i < MAX_HISTORY; i++) { if (history_free == NULL) { history_new = alloc_perm(sizeof(*history_new)); } else { history_new = history_free; history_free = history_free->next; } history_new->message = str_dup(""); history_new->next = history_prev; history_prev = history_new; } return history_new; } void strip_history(CHAR_DATA * ch) { HISTORY_DATA *pHistory; HISTORY_DATA *pHistory_next; for (pHistory = ch->pcdata->history; pHistory; pHistory = pHistory_next) { pHistory_next = pHistory->next; free_string(pHistory->message); pHistory->next = history_free; history_free = pHistory; } } void do_history(CHAR_DATA * ch, char *argument) { HISTORY_DATA *history; char buf[MAX_STRING_LENGTH]; if (IS_NPC(ch)) return; for (history = ch->pcdata->history; history; history = history->next) { if (strlen(history->message) > 3) { xprintf(buf, " %s\n\r", history->message); send_to_char(buf, ch); } } } void update_history(CHAR_DATA * ch, CHAR_DATA * talker, char *buf, char *argument, bool tell) { char message[MAX_STRING_LENGTH]; char tbuf[MAX_STRING_LENGTH]; char xbuf[MAX_STRING_LENGTH]; int i = 0; if (IS_NPC(ch)) return; xprintf(xbuf, "%s", line_indent(strip_ansi(argument), 22, 80)); if (!tell) { xprintf(tbuf, strip_ansi(buf)); while (tbuf[i] != '\0' && tbuf[i] != ' ') i++; tbuf[i] = '\0'; xprintf(message, "#C%-18s #0: #R%-s#n", tbuf, xbuf); } else { xprintf(message, "#0[#GT#0] #C%-14s #0: #R%-s#n", talker->name, xbuf); } attach_history(ch, message); return; } void attach_history(CHAR_DATA * ch, char *message) { HISTORY_DATA *history; HISTORY_DATA *history_prev1 = NULL; HISTORY_DATA *history_prev2 = NULL; if (history_free == NULL) { history = alloc_perm(sizeof(*history)); } else { history = history_free; history_free = history_free->next; } history->message = str_dup(message); history->next = ch->pcdata->history; ch->pcdata->history = history; for (history = ch->pcdata->history; history; history = history->next) { if (history_prev1) history_prev2 = history_prev1; history_prev1 = history; } history_prev2->next = NULL; free_string(history_prev1->message); history_prev1->next = history_free; history_free = history_prev1; } /* * Will remove the last line in the current note, * if there is a note, and it has a line to remove. */ void delete_last_line_in_note(CHAR_DATA * ch) { char buf[4 * MAX_STRING_LENGTH]; char *ptr; bool found = FALSE; int nCount = 0; buf[0] = '\0'; if (IS_NPC(ch)) return; if (ch->pcdata->in_progress->text == NULL) { send_to_char("No note to delete lines in.\n\r", ch); return; } if (strlen(ch->pcdata->in_progress->text) < 1) { send_to_char("Empty note, nothing to delete.\n\r", ch); return; } strcpy(buf, ch->pcdata->in_progress->text); ptr = buf; while (*ptr != '\0') { if (*ptr == '\n') nCount++; ptr++; } if (nCount == 1) { free_string(ch->pcdata->in_progress->text); ch->pcdata->in_progress->text = NULL; send_to_char("Entire note deleted.\n\r", ch); return; } else { while (*ptr != '\n' || !found) { if (*ptr == '\n') found = TRUE; ptr--; } } ptr++; *ptr = '\0'; free_string(ch->pcdata->in_progress->text); ch->pcdata->in_progress->text = str_dup(buf); send_to_char("Line deleted.\n\r", ch); }