/** The whisper command. * \param player the enactor. * \param arg1 name of the object to whisper to. * \param arg2 message to whisper. * \param noisy if 1, others overhear that a whisper has occurred. * \param pe_info the pe_info for evaluating interact locks */ void do_whisper(dbref player, const char *arg1, const char *arg2, int noisy, NEW_PE_INFO *pe_info) { dbref who; int key; const char *gap; char *tbuf, *tp; char *p; dbref good[100]; int gcount = 0; const char *head; int overheard; char *current; const char **start; char sname[BUFFER_LEN]; if (!arg1 || !*arg1) { notify(player, T("Whisper to whom?")); return; } if (!arg2 || !*arg2) { notify(player, T("Whisper what?")); return; } tp = tbuf = (char *) mush_malloc(BUFFER_LEN, "string"); if (!tbuf) mush_panic("Unable to allocate memory in do_whisper"); overheard = 0; head = arg1; start = &head; /* Figure out what kind of message */ gap = " "; switch (*arg2) { case SEMI_POSE_TOKEN: gap = ""; case POSE_TOKEN: key = 1; arg2++; break; default: key = 2; break; } *tp = '\0'; /* Make up a list of good and bad names */ while (head && *head) { current = next_in_list(start); who = match_result(player, current, TYPE_PLAYER, MAT_NEAR_THINGS | MAT_CONTAINER); if (!GoodObject(who) || !can_interact(player, who, INTERACT_HEAR, pe_info)) { safe_chr(' ', tbuf, &tp); safe_str_space(current, tbuf, &tp); if (GoodObject(who)) notify_format(player, T("%s can't hear you."), AName(who, AN_SYS, NULL)); } else { /* A good whisper */ good[gcount++] = who; if (gcount >= 100) { notify(player, T("Too many people to whisper to.")); break; } } } *tp = '\0'; if (*tbuf) notify_format(player, T("Unable to whisper to:%s"), tbuf); if (!gcount) { mush_free(tbuf, "string"); return; } /* Drunk wizards... */ if (Dark(player)) noisy = 0; /* Set up list of good names */ tp = tbuf; safe_str(T(" to "), tbuf, &tp); for (who = 0; who < gcount; who++) { if (noisy && (get_random32(0, 100) < (uint32_t) WHISPER_LOUDNESS)) overheard = 1; safe_itemizer(who + 1, (who == gcount - 1), ",", T("and"), " ", tbuf, &tp); safe_str(AName(good[who], AN_SAY, NULL), tbuf, &tp); } *tp = '\0'; if (key == 1) { notify_format(player, (gcount > 1) ? T("%s sense: %s%s%s") : T("%s senses: %s%s%s"), tbuf + 4, AName(player, AN_SAY, NULL), gap, arg2); p = tprintf("You sense: %s%s%s", AName(player, AN_SAY, NULL), gap, arg2); } else { notify_format(player, T("You whisper, \"%s\"%s."), arg2, tbuf); p = tprintf(T("%s whispers%s: %s"), AName(player, AN_SAY, NULL), gcount > 1 ? tbuf : "", arg2); } strcpy(sname, AName(player, AN_SAY, NULL)); for (who = 0; who < gcount; who++) { notify_must_puppet(good[who], p); if (Location(good[who]) != Location(player)) overheard = 0; } if (overheard) { dbref first = Contents(Location(player)); if (!GoodObject(first)) return; p = tprintf(T("%s whispers%s."), sname, tbuf); DOLIST(first, first) { overheard = 1; for (who = 0; who < gcount; who++) { if ((first == player) || (first == good[who])) { overheard = 0; break; } } if (overheard) notify_noecho(first, p); } }
static ATTR * attr_read(PENNFILE *f) { ATTR *a; char *tmp; dbref d = GOD; privbits flags = 0; a = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR"); if (!a) { mush_panic("Not enough memory to add attribute in attr_read()!"); return NULL; } AL_NAME(a) = NULL; a->data = NULL_CHUNK_REFERENCE; AL_FLAGS(a) = 0; AL_CREATOR(a) = GOD; a->next = NULL; db_read_this_labeled_string(f, "name", &tmp); if (!good_atr_name(tmp)) { do_rawlog(LT_ERR, "Invalid attribute name '%s' in db.", tmp); (void) getstring_noalloc(f); /* flags */ (void) getstring_noalloc(f); /* creator */ (void) getstring_noalloc(f); /* data */ free_standard_attr(a, 0); return NULL; } AL_NAME(a) = strdup(tmp); db_read_this_labeled_string(f, "flags", &tmp); if (tmp && *tmp && strcasecmp(tmp, "none")) { flags = list_to_privs(attr_privs_db, tmp, 0); if (!flags) { do_rawlog(LT_ERR, "Invalid attribute flags for '%s' in db.", AL_NAME(a)); free((char *) AL_NAME(a)); (void) getstring_noalloc(f); /* creator */ (void) getstring_noalloc(f); /* data */ free_standard_attr(a, 0); return NULL; } } AL_FLAGS(a) = flags; db_read_this_labeled_dbref(f, "creator", &d); AL_CREATOR(a) = d; db_read_this_labeled_string(f, "data", &tmp); if (!tmp || !*tmp || !(AL_FLAGS(a) & (AF_ENUM | AF_RLIMIT))) { a->data = NULL_CHUNK_REFERENCE; } else if (AL_FLAGS(a) & AF_ENUM) { /* Store string as it is */ char *t = compress(tmp); a->data = chunk_create(t, strlen(t), 0); free(t); } else if (AL_FLAGS(a) & AF_RLIMIT) { /* Need to validate regexp */ char *t; pcre *re; const char *errptr; int erroffset; re = pcre_compile(tmp, PCRE_CASELESS, &errptr, &erroffset, tables); if (!re) { do_rawlog(LT_ERR, "Invalid regexp in limit for attribute '%s' in db.", AL_NAME(a)); free_standard_attr(a, 0); return NULL; } pcre_free(re); /* don't need it, just needed to check it */ t = compress(tmp); a->data = chunk_create(t, strlen(t), 0); free(t); } return a; }