// speech.cpp -- Commands which involve speaking.
//
// $Id: speech.cpp,v 1.21 2005/10/12 04:28:27 sdennis Exp $
//
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
#include "attrs.h"
#include "interface.h"
#include "powers.h"
#ifdef REALITY_LVLS
#include "levels.h"
#endif
char *modSpeech(dbref player, char *message, bool bWhich, char *command)
{
dbref aowner;
int aflags;
char *mod = atr_get(player, bWhich ? A_SPEECHMOD : A_SAYSTRING,
&aowner, &aflags);
if ( mod[0] == '\0'
|| MuxAlarm.bAlarmed)
{
free_lbuf(mod);
return NULL;
}
char *mod_orig = mod;
char *new_message = alloc_lbuf("modspeech");
char *t_ptr = new_message;
char *args[2];
args[0] = message;
args[1] = command;
mux_exec(new_message, &t_ptr, player, player, player,
EV_FCHECK | EV_EVAL | EV_TOP, &mod, args, 2);
free_lbuf(mod_orig);
return new_message;
}
static int idle_timeout_val(dbref player)
{
// If IDLETIMEOUT attribute is not present, the value
// returned will be zero.
//
dbref aowner;
int aflags;
char *ITbuffer = atr_get(player, A_IDLETMOUT, &aowner, &aflags);
int idle_timeout = mux_atol(ITbuffer);
free_lbuf(ITbuffer);
return idle_timeout;
}
bool sp_ok(dbref player)
{
if ( Gagged(player)
&& !Wizard(player))
{
notify(player, "Sorry. Gagged players cannot speak.");
return false;
}
if (!mudconf.robot_speak)
{
if (Robot(player) && !Controls(player, Location(player)))
{
notify(player, "Sorry, robots may not speak in public.");
return false;
}
}
if (Auditorium(Location(player)))
{
if (!could_doit(player, Location(player), A_LSPEECH))
{
notify(player, "Sorry, you may not speak in this place.");
return false;
}
}
return true;
}
void wall_broadcast(int target, dbref player, char *message)
{
DESC *d;
DESC_ITER_CONN(d)
{
switch (target)
{
case SHOUT_WIZARD:
if (Wizard(d->player))
{
notify_with_cause(d->player, player, message);
}
break;
case SHOUT_ADMIN:
if (WizRoy(d->player))
{
notify_with_cause(d->player, player, message);
}
break;
default:
notify_with_cause(d->player, player, message);
break;
}
}
}
static void say_shout(int target, const char *prefix, int flags,
dbref player, char *message)
{
char *p;
if (flags & SAY_NOTAG)
{
p = tprintf("%s%s", Moniker(player), message);
}
else
{
p = tprintf("%s%s%s", prefix, Moniker(player), message);
}
wall_broadcast(target, player, p);
}
static const char *announce_msg = "Announcement: ";
static const char *broadcast_msg = "Broadcast: ";
static const char *admin_msg = "Admin: ";
void do_think(dbref executor, dbref caller, dbref enactor, int key,
char *message)
{
char *str, *buf, *bp;
buf = bp = alloc_lbuf("do_think");
str = message;
mux_exec(buf, &bp, executor, caller, enactor, EV_FCHECK | EV_EVAL | EV_TOP,
&str, (char **)NULL, 0);
*bp = '\0';
notify(executor, buf);
free_lbuf(buf);
}
void do_say(dbref executor, dbref caller, dbref enactor, int key, char *message)
{
// Make sure speaker is somewhere if speaking in a place
//
dbref loc = where_is(executor);
if ( !( Good_obj(loc)
& sp_ok(executor)))
{
return;
}
int say_flags, depth;
// Convert prefix-coded messages into the normal type
//
say_flags = key & (SAY_NOEVAL | SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
key &= ~(SAY_NOEVAL | SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
if (key == SAY_PREFIX)
{
switch (*message)
{
case '"':
message++;
key = SAY_SAY;
break;
case ':':
message++;
if (*message == ' ')
{
message++;
key = SAY_POSE_NOSPC;
}
else
{
key = SAY_POSE;
}
break;
case ';':
message++;
key = SAY_POSE_NOSPC;
break;
case '\\':
message++;
// FALLTHROUGH
//
default:
key = SAY_EMIT;
break;
}
}
char *command = "";
if (SAY_SAY == key)
{
command = "say";
}
else if (SAY_POSE == key || SAY_POSE_NOSPC == key)
{
command = "pose";
}
else if (SAY_EMIT == key)
{
command = "@emit";
}
// Parse speechmod if present.
//
char *messageOrig = message;
char *messageNew = NULL;
if (!(say_flags & SAY_NOEVAL))
{
messageNew = modSpeech(executor, message, true, command);
if (messageNew)
{
message = messageNew;
}
}
// Send the message on its way
//
char *saystring;
switch (key)
{
case SAY_SAY:
saystring = modSpeech(executor, messageOrig, false, command);
if (saystring)
{
notify_saypose(executor, tprintf("%s %s \"%s\"",
Moniker(executor), saystring, message));
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, executor, tprintf("%s %s \"%s\"", Moniker(executor), saystring, message), MSG_SAYPOSE);
#else
notify_except(loc, executor, executor, tprintf("%s %s \"%s\"", Moniker(executor), saystring, message), MSG_SAYPOSE);
#endif
free_lbuf(saystring);
}
else
{
notify_saypose(executor, tprintf("You say, \"%s\"", message));
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, executor, tprintf("%s says, \"%s\"", Moniker(executor), message), MSG_SAYPOSE);
#else
notify_except(loc, executor, executor, tprintf("%s says, \"%s\"", Moniker(executor), message), MSG_SAYPOSE);
#endif
}
break;
case SAY_POSE:
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, -1, tprintf("%s %s", Moniker(executor), message), MSG_SAYPOSE);
#else
notify_all_from_inside_saypose(loc, executor, tprintf("%s %s", Moniker(executor), message));
#endif
break;
case SAY_POSE_NOSPC:
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, -1, tprintf("%s%s", Moniker(executor), message), MSG_SAYPOSE);
#else
notify_all_from_inside_saypose(loc, executor, tprintf("%s%s", Moniker(executor), message));
#endif
break;
case SAY_EMIT:
if ( (say_flags & SAY_HERE)
|| (say_flags & SAY_HTML)
|| !say_flags)
{
if (say_flags & SAY_HTML)
{
notify_all_from_inside_html(loc, executor, message);
}
else
{
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, -1, message, SAY_EMIT);
#else
notify_all_from_inside(loc, executor, message);
#endif
}
}
if (say_flags & SAY_ROOM)
{
if ( isRoom(loc)
&& (say_flags & SAY_HERE))
{
if (messageNew)
{
free_lbuf(messageNew);
}
return;
}
for (depth = 0; !isRoom(loc) && (depth < 20); depth++)
{
loc = Location(loc);
if ( !Good_obj(loc)
|| (loc == Location(loc)))
{
if (messageNew)
{
free_lbuf(messageNew);
}
return;
}
}
if (isRoom(loc))
{
#ifdef REALITY_LVLS
notify_except_rlevel(loc, executor, -1, message, -1);
#else
notify_all_from_inside(loc, executor, message);
#endif
}
}
break;
}
if (messageNew)
{
free_lbuf(messageNew);
}
}
void do_shout(dbref executor, dbref caller, dbref enactor, int key,
char *message)
{
char *p;
char *buf2, *bp;
int say_flags = key & (SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
key &= ~(SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
// Parse speechmod if present.
//
char *messageNew = modSpeech(executor, message, true, "@wall");
if (messageNew)
{
message = messageNew;
}
switch (key)
{
case SHOUT_SHOUT:
switch (*message)
{
case ':':
message[0] = ' ';
say_shout(0, announce_msg, say_flags, executor, message);
break;
case ';':
message++;
say_shout(0, announce_msg, say_flags, executor, message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_shout.shout");
bp = buf2;
safe_str(" shouts, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
*bp = '\0';
say_shout(0, announce_msg, say_flags, executor, buf2);
free_lbuf(buf2);
}
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
log_name(executor);
log_text(" shouts: ");
log_text(message);
ENDLOG;
break;
case SHOUT_WIZSHOUT:
switch (*message)
{
case ':':
message[0] = ' ';
say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor,
message);
break;
case ';':
message++;
say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor,
message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_shout.wizshout");
bp = buf2;
safe_str(" says, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
*bp = '\0';
say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor, buf2);
free_lbuf(buf2);
}
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
log_name(executor);
log_text(" broadcasts: '");
log_text(message);
log_text("'");
ENDLOG;
break;
case SHOUT_ADMINSHOUT:
switch (*message)
{
case ':':
message[0] = ' ';
say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
message);
break;
case ';':
message++;
say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_shout.adminshout");
bp = buf2;
safe_str(" says, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
*bp = '\0';
say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
buf2);
free_lbuf(buf2);
}
STARTLOG(LOG_SHOUTS, "WIZ", "ASHOUT");
log_name(executor);
log_text(" yells: ");
log_text(message);
ENDLOG;
break;
case SHOUT_WALLPOSE:
if (say_flags & SAY_NOTAG)
{
p = tprintf("%s %s", Moniker(executor), message);
}
else
{
p = tprintf("Announcement: %s %s", Moniker(executor),
message);
}
wall_broadcast(0, executor, p);
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
log_name(executor);
log_text(" WALLposes: ");
log_text(message);
ENDLOG;
break;
case SHOUT_WIZPOSE:
if (say_flags & SAY_NOTAG)
{
p = tprintf("%s %s", Moniker(executor), message);
}
else
{
p = tprintf("Broadcast: %s %s", Moniker(executor), message);
}
wall_broadcast(SHOUT_WIZARD, executor, p);
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
log_name(executor);
log_text(" WIZposes: ");
log_text(message);
ENDLOG;
break;
case SHOUT_WALLEMIT:
if (say_flags & SAY_NOTAG)
{
p = tprintf("%s", message);
}
else
{
p = tprintf("Announcement: %s", message);
}
wall_broadcast(0, executor, p);
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
log_name(executor);
log_text(" WALLemits: ");
log_text(message);
ENDLOG;
break;
case SHOUT_WIZEMIT:
if (say_flags & SAY_NOTAG)
{
p = tprintf("%s", message);
}
else
{
p = tprintf("Broadcast: %s", message);
}
wall_broadcast(SHOUT_WIZARD, executor, p);
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
log_name(executor);
log_text(" WIZemit: ");
log_text(message);
ENDLOG;
break;
}
if (messageNew)
{
free_lbuf(messageNew);
}
}
/* ---------------------------------------------------------------------------
* do_page: Handle the page command.
* Page-pose code from shadow@prelude.cc.purdue.
*/
static void page_return(dbref player, dbref target, const char *tag,
int anum, const char *dflt)
{
if (MuxAlarm.bAlarmed)
{
return;
}
dbref aowner;
int aflags;
char *str, *str2, *buf, *bp;
str = atr_pget(target, anum, &aowner, &aflags);
if (*str)
{
str2 = bp = alloc_lbuf("page_return");
buf = str;
mux_exec(str2, &bp, target, player, player,
EV_FCHECK | EV_EVAL | EV_TOP | EV_NO_LOCATION, &buf,
(char **)NULL, 0);
*bp = '\0';
if (*str2)
{
CLinearTimeAbsolute ltaNow;
ltaNow.GetLocal();
FIELDEDTIME ft;
ltaNow.ReturnFields(&ft);
char *p = tprintf("%s message from %s: %s", tag,
Moniker(target), str2);
notify_with_cause_ooc(player, target, p);
p = tprintf("[%d:%02d] %s message sent to %s.", ft.iHour,
ft.iMinute, tag, Moniker(player));
notify_with_cause_ooc(target, player, p);
}
free_lbuf(str2);
}
else if (dflt && *dflt)
{
notify_with_cause_ooc(player, target, dflt);
}
free_lbuf(str);
}
static bool page_check(dbref player, dbref target)
{
if (!payfor(player, Guest(player) ? 0 : mudconf.pagecost))
{
notify(player, tprintf("You don't have enough %s.", mudconf.many_coins));
}
else if (!Connected(target))
{
page_return(player, target, "Away", A_AWAY,
tprintf("Sorry, %s is not connected.", Moniker(target)));
}
else if (!could_doit(player, target, A_LPAGE))
{
if ( Can_Hide(target)
&& Hidden(target)
&& !See_Hidden(player))
{
page_return(player, target, "Away", A_AWAY,
tprintf("Sorry, %s is not connected.", Moniker(target)));
}
else
{
page_return(player, target, "Reject", A_REJECT,
tprintf("Sorry, %s is not accepting pages.", Moniker(target)));
}
}
else if (!could_doit(target, player, A_LPAGE))
{
char *p;
if (Wizard(player))
{
p = tprintf("Warning: %s can't return your page.",
Moniker(target));
notify(player, p);
return true;
}
else
{
p = tprintf("Sorry, %s can't return your page.",
Moniker(target));
notify(player, p);
return false;
}
}
else
{
return true;
}
return false;
}
// The combinations are:
//
// nargs arg1[0] arg2[0]
// '' 1 '\0' '\0' Report LastPaged to player.
// 'a' 1 'a' '\0' Page LastPaged with A
// 'a=' 2 'a' '\0' Page A. LastPaged <- A
// '=b' 2 '\0' 'b' Page LastPaged with B
// 'a=b' 2 'a' 'b' Page A with B. LastPaged <- A
// 'a=b1=[b2=]*...' All treated the same as 'a=b'.
//
void do_page
(
dbref executor,
dbref caller,
dbref enactor,
int key,
int nargs,
char *arg1,
char *arg2
)
{
int nPlayers = 0;
dbref aPlayers[(LBUF_SIZE+1)/2];
// Either we have been given a recipient list, or we are relying on an
// existing A_LASTPAGE.
//
bool bModified = false;
if ( nargs == 2
&& arg1[0] != '\0')
{
bModified = true;
char *p = arg1;
while (*p != '\0')
{
char *q = strchr(p, '"');
if (q)
{
*q = '\0';
}
// Decode space-delimited or comma-delimited recipients.
//
MUX_STRTOK_STATE tts;
mux_strtok_src(&tts, p);
mux_strtok_ctl(&tts, ", ");
char *r;
for (r = mux_strtok_parse(&tts); r; r = mux_strtok_parse(&tts))
{
dbref target = lookup_player(executor, r, true);
if (target != NOTHING)
{
aPlayers[nPlayers++] = target;
}
else
{
notify(executor, tprintf("I don't recognize \"%s\".", r));
}
}
if (q)
{
p = q + 1;
// Handle quoted named.
//
q = strchr(p, '"');
if (q)
{
*q = '\0';
}
dbref target = lookup_player(executor, p, true);
if (target != NOTHING)
{
aPlayers[nPlayers++] = target;
}
else
{
notify(executor, tprintf("I don't recognize \"%s\".", p));
}
if (q)
{
p = q + 1;
}
else
{
break;
}
}
else
{
break;
}
}
}
else
{
// Need to decode the A_LASTPAGE.
//
dbref aowner;
int aflags;
char *pLastPage = atr_get(executor, A_LASTPAGE, &aowner, &aflags);
MUX_STRTOK_STATE tts;
mux_strtok_src(&tts, pLastPage);
mux_strtok_ctl(&tts, " ");
char *p;
for (p = mux_strtok_parse(&tts); p; p = mux_strtok_parse(&tts))
{
dbref target = mux_atol(p);
if ( Good_obj(target)
&& isPlayer(target))
{
aPlayers[nPlayers++] = target;
}
else
{
notify(executor, tprintf("I don't recognize #%d.", target));
bModified = true;
}
}
free_lbuf(pLastPage);
}
int nValid = nPlayers;
// Remove duplicate dbrefs.
//
int i;
for (i = 0; i < nPlayers-1; i++)
{
if (aPlayers[i] != NOTHING)
{
int j;
for (j = i+1; j < nPlayers; j++)
{
if (aPlayers[j] == aPlayers[i])
{
aPlayers[j] = NOTHING;
bModified = true;
nValid--;
}
}
}
}
// If we are doing more than reporting, we have some other dbref
// validation to do.
//
if ( nargs == 2
|| arg1[0] != '\0')
{
for (i = 0; i < nPlayers; i++)
{
if ( Good_obj(aPlayers[i])
&& !page_check(executor, aPlayers[i]))
{
aPlayers[i] = NOTHING;
bModified = true;
nValid--;
}
}
}
if (bModified)
{
// Our aPlayers could be different than the one encoded on A_LASTPAGE.
// Update the database.
//
ITL itl;
char *pBuff = alloc_lbuf("do_page.lastpage");
char *pBufc = pBuff;
ItemToList_Init(&itl, pBuff, &pBufc);
for (i = 0; i < nPlayers; i++)
{
if ( Good_obj(aPlayers[i])
&& !ItemToList_AddInteger(&itl, aPlayers[i]))
{
break;
}
}
ItemToList_Final(&itl);
atr_add_raw(executor, A_LASTPAGE, pBuff);
free_lbuf(pBuff);
}
// Verify that the recipient list isn't empty.
//
if (nValid == 0)
{
if ( nargs == 1
&& arg1[0] == '\0')
{
notify(executor, "You have not paged anyone.");
}
else
{
notify(executor, "No one to page.");
}
return;
}
// Build a friendly representation of the recipient list.
//
char *aFriendly = alloc_lbuf("do_page.friendly");
char *pFriendly = aFriendly;
if (nValid > 1)
{
safe_chr('(', aFriendly, &pFriendly);
}
bool bFirst = true;
for (i = 0; i < nPlayers; i++)
{
if (aPlayers[i] != NOTHING)
{
if (bFirst)
{
bFirst = false;
}
else
{
safe_copy_buf(", ", 2, aFriendly, &pFriendly);
}
safe_str(Moniker(aPlayers[i]), aFriendly, &pFriendly);
}
}
if (nValid > 1)
{
safe_chr(')', aFriendly, &pFriendly);
}
*pFriendly = '\0';
// We may be able to proceed directly to the reporting case.
//
if ( nargs == 1
&& arg1[0] == '\0')
{
notify(executor, tprintf("You last paged %s.", aFriendly));
free_lbuf(aFriendly);
return;
}
// Build messages.
//
char *omessage = alloc_lbuf("do_page.omessage");
char *imessage = alloc_lbuf("do_page.imessage");
char *omp = omessage;
char *imp = imessage;
char *pMessage;
if (nargs == 1)
{
// 'page A' form.
//
pMessage = arg1;
}
else
{
// 'page A=', 'page =B', and 'page A=B' forms.
//
pMessage = arg2;
}
int pageMode;
switch (*pMessage)
{
case '\0':
pageMode = 1;
break;
case ':':
pageMode = 2;
pMessage++;
break;
case ';':
pageMode = 3;
pMessage++;
break;
case '"':
pMessage++;
// FALL THROUGH
default:
pageMode = 0;
}
char *newMessage = modSpeech(executor, pMessage, true, "page");
if (newMessage)
{
pMessage = newMessage;
}
switch (pageMode)
{
case 1:
// 'page A=' form.
//
if (nValid == 1)
{
safe_tprintf_str(omessage, &omp, "From afar, %s pages you.",
Moniker(executor));
}
else
{
safe_tprintf_str(omessage, &omp, "From afar, %s pages %s.",
Moniker(executor), aFriendly);
}
safe_tprintf_str(imessage, &imp, "You page %s.", aFriendly);
break;
case 2:
safe_str("From afar, ", omessage, &omp);
if (nValid > 1)
{
safe_tprintf_str(omessage, &omp, "to %s: ", aFriendly);
}
safe_tprintf_str(omessage, &omp, "%s %s", Moniker(executor), pMessage);
safe_tprintf_str(imessage, &imp, "Long distance to %s: %s %s",
aFriendly, Moniker(executor), pMessage);
break;
case 3:
safe_str("From afar, ", omessage, &omp);
if (nValid > 1)
{
safe_tprintf_str(omessage, &omp, "to %s: ", aFriendly);
}
safe_tprintf_str(omessage, &omp, "%s%s", Moniker(executor), pMessage);
safe_tprintf_str(imessage, &imp, "Long distance to %s: %s%s",
aFriendly, Moniker(executor), pMessage);
break;
default:
if (nValid > 1)
{
safe_tprintf_str(omessage, &omp, "To %s, ", aFriendly);
}
safe_tprintf_str(omessage, &omp, "%s pages: %s", Moniker(executor),
pMessage);
safe_tprintf_str(imessage, &imp, "You paged %s with '%s'",
aFriendly, pMessage);
break;
}
free_lbuf(aFriendly);
// Send message to recipients.
//
for (i = 0; i < nPlayers; i++)
{
dbref target = aPlayers[i];
if (target != NOTHING)
{
notify_with_cause_ooc(target, executor, omessage);
if (fetch_idle(target) >= idle_timeout_val(target))
{
page_return(executor, target, "Idle", A_IDLE, NULL);
}
}
}
free_lbuf(omessage);
// Send message to sender.
//
notify(executor, imessage);
free_lbuf(imessage);
if (newMessage)
{
free_lbuf(newMessage);
}
}
/* ---------------------------------------------------------------------------
* do_pemit: Messages to specific players, or to all but specific players.
*/
void whisper_pose(dbref player, dbref target, char *message, bool bSpace)
{
char *newMessage = modSpeech(player, message, true, "whisper");
if (newMessage)
{
message = newMessage;
}
char *buff = alloc_lbuf("do_pemit.whisper.pose");
strcpy(buff, Moniker(player));
notify(player, tprintf("%s senses \"%s%s%s\"", Moniker(target), buff,
bSpace ? " " : "", message));
notify_with_cause(target, player, tprintf("You sense %s%s%s", buff,
bSpace ? " " : "", message));
free_lbuf(buff);
if (newMessage)
{
free_lbuf(newMessage);
}
}
void do_pemit_single
(
dbref player,
int key,
bool bDoContents,
int pemit_flags,
char *recipient,
int chPoseType,
char *message
)
{
dbref target, loc;
char *buf2, *bp;
int depth;
bool ok_to_do = false;
switch (key)
{
case PEMIT_FSAY:
case PEMIT_FPOSE:
case PEMIT_FPOSE_NS:
case PEMIT_FEMIT:
target = match_controlled(player, recipient);
if (target == NOTHING)
{
return;
}
ok_to_do = true;
break;
default:
init_match(player, recipient, TYPE_PLAYER);
match_everything(0);
target = match_result();
}
char *newMessage = NULL;
char *saystring = NULL;
char *p;
switch (target)
{
case NOTHING:
switch (key)
{
case PEMIT_WHISPER:
notify(player, "Whisper to whom?");
break;
case PEMIT_PEMIT:
notify(player, "Emit to whom?");
break;
case PEMIT_OEMIT:
notify(player, "Emit except to whom?");
break;
default:
notify(player, "Sorry.");
break;
}
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
// Enforce locality constraints.
//
if ( !ok_to_do
&& ( nearby(player, target)
|| Long_Fingers(player)
|| Controls(player, target)))
{
ok_to_do = true;
}
if ( !ok_to_do
&& key == PEMIT_PEMIT
&& isPlayer(target)
&& mudconf.pemit_players)
{
if (!page_check(player, target))
{
return;
}
ok_to_do = true;
}
if ( !ok_to_do
&& ( !mudconf.pemit_any
|| key != PEMIT_PEMIT))
{
notify(player, "You are too far away to do that.");
return;
}
if ( bDoContents
&& !Controls(player, target)
&& !mudconf.pemit_any)
{
notify(player, NOPERM_MESSAGE);
return;
}
loc = where_is(target);
switch (key)
{
case PEMIT_PEMIT:
if (bDoContents)
{
if (Has_contents(target))
{
notify_all_from_inside(target, player, message);
}
}
else
{
if (pemit_flags & PEMIT_HTML)
{
notify_with_cause_html(target, player, message);
}
else
{
notify_with_cause(target, player, message);
}
}
break;
case PEMIT_OEMIT:
notify_except(Location(target), player, target, message, 0);
break;
case PEMIT_WHISPER:
if ( isPlayer(target)
&& !Connected(target))
{
page_return(player, target, "Away", A_AWAY,
tprintf("Sorry, %s is not connected.", Moniker(target)));
return;
}
switch (chPoseType)
{
case ':':
message++;
whisper_pose(player, target, message, true);
break;
case ';':
message++;
whisper_pose(player, target, message, false);
break;
case '"':
message++;
default:
newMessage = modSpeech(player, message, true, "whisper");
if (newMessage)
{
message = newMessage;
}
notify(player, tprintf("You whisper \"%s\" to %s.", message,
Moniker(target)));
notify_with_cause(target, player,
tprintf("%s whispers \"%s\"", Moniker(player), message));
if (newMessage)
{
free_lbuf(newMessage);
}
}
if ( !mudconf.quiet_whisper
&& !Wizard(player))
{
loc = where_is(player);
if (loc != NOTHING)
{
buf2 = alloc_lbuf("do_pemit.whisper.buzz");
bp = buf2;
safe_str(Moniker(player), buf2, &bp);
safe_str(" whispers something to ", buf2, &bp);
safe_str(Moniker(target), buf2, &bp);
*bp = '\0';
notify_except2(loc, player, player, target, buf2);
free_lbuf(buf2);
}
}
break;
case PEMIT_FSAY:
newMessage = modSpeech(target, message, true, "@fsay");
if (newMessage)
{
message = newMessage;
}
notify(target, tprintf("You say, \"%s\"", message));
if (loc != NOTHING)
{
saystring = modSpeech(target, message, false, "@fsay");
if (saystring)
{
p = tprintf("%s %s \"%s\"", Moniker(target),
saystring, message);
notify_except(loc, player, target, p, 0);
}
else
{
p = tprintf("%s says, \"%s\"", Moniker(target),
message);
notify_except(loc, player, target, p, 0);
}
}
if (saystring)
{
free_lbuf(saystring);
}
if (newMessage)
{
free_lbuf(newMessage);
}
break;
case PEMIT_FPOSE:
newMessage = modSpeech(target, message, true, "@fpose");
if (newMessage)
{
message = newMessage;
}
p = tprintf("%s %s", Moniker(target), message);
notify_all_from_inside(loc, player, p);
if (newMessage)
{
free_lbuf(newMessage);
}
break;
case PEMIT_FPOSE_NS:
newMessage = modSpeech(target, message, true, "@fpose");
if (newMessage)
{
message = newMessage;
}
p = tprintf("%s%s", Moniker(target), message);
notify_all_from_inside(loc, player, p);
if (newMessage)
{
free_lbuf(newMessage);
}
break;
case PEMIT_FEMIT:
if ( (pemit_flags & PEMIT_HERE)
|| !pemit_flags)
{
notify_all_from_inside(loc, player, message);
}
if (pemit_flags & PEMIT_ROOM)
{
if ( isRoom(loc)
&& (pemit_flags & PEMIT_HERE))
{
return;
}
depth = 0;
while ( !isRoom(loc)
&& depth++ < 20)
{
loc = Location(loc);
if ( loc == NOTHING
|| loc == Location(loc))
{
return;
}
}
if (isRoom(loc))
{
notify_all_from_inside(loc, player, message);
}
}
break;
}
}
}
void do_pemit_list
(
dbref player,
int key,
bool bDoContents,
int pemit_flags,
char *list,
int chPoseType,
char *message
)
{
// Send a message to a list of dbrefs. The list is destructively
// modified.
//
if ( message[0] == '\0'
|| list[0] == '\0')
{
return;
}
char *p;
MUX_STRTOK_STATE tts;
mux_strtok_src(&tts, list);
mux_strtok_ctl(&tts, " ");
for (p = mux_strtok_parse(&tts); p; p = mux_strtok_parse(&tts))
{
do_pemit_single(player, key, bDoContents, pemit_flags, p, chPoseType,
message);
}
}
void do_pemit
(
dbref executor,
dbref caller,
dbref enactor,
int key,
int nargs,
char *recipient,
char *message
)
{
if (nargs < 2)
{
return;
}
// Decode PEMIT_CONENTS and PEMIT_LIST and remove from key.
//
bool bDoContents = false;
if (key & PEMIT_CONTENTS)
{
bDoContents = true;
}
bool bDoList = false;
if (key & PEMIT_LIST)
{
bDoList = true;
}
key &= ~(PEMIT_CONTENTS | PEMIT_LIST);
// Decode PEMIT_HERE, PEMIT_ROOM, PEMIT_HTML and remove from key.
//
int mask = PEMIT_HERE | PEMIT_ROOM | PEMIT_HTML;
int pemit_flags = key & mask;
key &= ~mask;
int chPoseType = *message;
if (key == PEMIT_WHISPER && chPoseType == ':')
{
message[0] = ' ';
}
if (bDoList)
{
do_pemit_list(executor, key, bDoContents, pemit_flags, recipient,
chPoseType, message);
}
else
{
do_pemit_single(executor, key, bDoContents, pemit_flags, recipient,
chPoseType, message);
}
}