mux/src/speech.cpp

Go to the documentation of this file.
00001 // speech.cpp -- Commands which involve speaking.
00002 //
00003 // $Id: speech.cpp,v 1.24 2007/04/14 04:57:05 sdennis Exp $
00004 //
00005 
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010 
00011 #include "attrs.h"
00012 #include "command.h"
00013 #include "interface.h"
00014 #include "powers.h"
00015 #ifdef REALITY_LVLS
00016 #include "levels.h"
00017 #endif
00018 
00019 char *modSpeech(dbref player, char *message, bool bWhich, char *command)
00020 {
00021     dbref aowner;
00022     int aflags;
00023     char *mod = atr_get(player, bWhich ? A_SPEECHMOD : A_SAYSTRING,
00024         &aowner, &aflags);
00025 
00026     if (  mod[0] == '\0'
00027        || MuxAlarm.bAlarmed)
00028     {
00029         free_lbuf(mod);
00030         return NULL;
00031     }
00032 
00033     char *mod_orig = mod;
00034     char *new_message = alloc_lbuf("modspeech");
00035     char *t_ptr = new_message;
00036     char *args[2];
00037     args[0] = message;
00038     args[1] = command;
00039     mux_exec(new_message, &t_ptr, player, player, player,
00040         EV_FCHECK | EV_EVAL | EV_TOP, &mod, args, 2);
00041     *t_ptr = '\0';
00042     free_lbuf(mod_orig);
00043     return new_message;
00044 }
00045 
00046 static int idle_timeout_val(dbref player)
00047 {
00048     // If IDLETIMEOUT attribute is not present, the value
00049     // returned will be zero.
00050     //
00051     dbref aowner;
00052     int aflags;
00053     char *ITbuffer = atr_get(player, A_IDLETMOUT, &aowner, &aflags);
00054     int idle_timeout = mux_atol(ITbuffer);
00055     free_lbuf(ITbuffer);
00056     return idle_timeout;
00057 }
00058 
00059 static bool sp_ok(dbref player)
00060 {
00061     if (  Gagged(player)
00062        && !Wizard(player))
00063     {
00064         notify(player, "Sorry. Gagged players cannot speak.");
00065         return false;
00066     }
00067 
00068     if (!mudconf.robot_speak)
00069     {
00070         if (Robot(player) && !Controls(player, Location(player)))
00071         {
00072             notify(player, "Sorry, robots may not speak in public.");
00073             return false;
00074         }
00075     }
00076     if (Auditorium(Location(player)))
00077     {
00078         if (!could_doit(player, Location(player), A_LSPEECH))
00079         {
00080             notify(player, "Sorry, you may not speak in this place.");
00081             return false;
00082         }
00083     }
00084     return true;
00085 }
00086 
00087 static void wall_broadcast(int target, dbref player, char *message)
00088 {
00089     DESC *d;
00090     DESC_ITER_CONN(d)
00091     {
00092         switch (target)
00093         {
00094         case SHOUT_WIZARD:
00095 
00096             if (Wizard(d->player))
00097             {
00098                 notify_with_cause(d->player, player, message);
00099             }
00100             break;
00101 
00102         case SHOUT_ADMIN:
00103 
00104             if (WizRoy(d->player))
00105             {
00106                 notify_with_cause(d->player, player, message);
00107             }
00108             break;
00109 
00110         default:
00111 
00112             notify_with_cause(d->player, player, message);
00113             break;
00114         }
00115     }
00116 }
00117 
00118 static void say_shout(int target, const char *prefix, int flags,
00119     dbref player, char *message)
00120 {
00121     char *p;
00122     if (flags & SAY_NOTAG)
00123     {
00124         p = tprintf("%s%s", Moniker(player), message);
00125     }
00126     else
00127     {
00128         p = tprintf("%s%s%s", prefix, Moniker(player), message);
00129     }
00130     wall_broadcast(target, player, p);
00131 }
00132 
00133 static const char *announce_msg = "Announcement: ";
00134 static const char *broadcast_msg = "Broadcast: ";
00135 static const char *admin_msg = "Admin: ";
00136 
00137 void do_think(dbref executor, dbref caller, dbref enactor, int key,
00138     char *message)
00139 {
00140     UNUSED_PARAMETER(key);
00141 
00142     char *str, *buf, *bp;
00143 
00144     buf = bp = alloc_lbuf("do_think");
00145     str = message;
00146     mux_exec(buf, &bp, executor, caller, enactor, EV_FCHECK | EV_EVAL | EV_TOP,
00147              &str, (char **)NULL, 0);
00148     *bp = '\0';
00149     notify(executor, buf);
00150     free_lbuf(buf);
00151 }
00152 
00153 void do_say(dbref executor, dbref caller, dbref enactor, int key, char *message)
00154 {
00155     UNUSED_PARAMETER(caller);
00156     UNUSED_PARAMETER(enactor);
00157 
00158     // Make sure speaker is somewhere if speaking in a place
00159     //
00160     dbref loc = where_is(executor);
00161     if ( !(  Good_obj(loc)
00162           && sp_ok(executor)))
00163     {
00164         return;
00165     }
00166 
00167     int say_flags, depth;
00168 
00169     // Convert prefix-coded messages into the normal type
00170     //
00171     say_flags = key & (SAY_NOEVAL | SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
00172     key &= ~(SAY_NOEVAL | SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
00173 
00174     if (key == SAY_PREFIX)
00175     {
00176         switch (*message)
00177         {
00178         case '"':
00179             message++;
00180             key = SAY_SAY;
00181             break;
00182 
00183         case ':':
00184             message++;
00185             if (*message == ' ')
00186             {
00187                 message++;
00188                 key = SAY_POSE_NOSPC;
00189             }
00190             else
00191             {
00192                 key = SAY_POSE;
00193             }
00194             break;
00195 
00196         case ';':
00197             message++;
00198             key = SAY_POSE_NOSPC;
00199             break;
00200 
00201         case '\\':
00202             message++;
00203 
00204             // FALLTHROUGH
00205             //
00206 
00207         default:
00208             key = SAY_EMIT;
00209             break;
00210         }
00211     }
00212 
00213     char *command = "";
00214     if (SAY_SAY == key)
00215     {
00216         command = "say";
00217     }
00218     else if (SAY_POSE == key || SAY_POSE_NOSPC == key)
00219     {
00220         command = "pose";
00221     }
00222     else if (SAY_EMIT == key)
00223     {
00224         command = "@emit";
00225     }
00226 
00227     // Parse speechmod if present.
00228     //
00229     char *messageOrig = message;
00230     char *messageNew = NULL;
00231     if (!(say_flags & SAY_NOEVAL))
00232     {
00233         messageNew = modSpeech(executor, message, true, command);
00234         if (messageNew)
00235         {
00236             message = messageNew;
00237         }
00238     }
00239 
00240     // Send the message on its way
00241     //
00242     char *saystring;
00243     switch (key)
00244     {
00245     case SAY_SAY:
00246         saystring = modSpeech(executor, messageOrig, false, command);
00247         if (saystring)
00248         {
00249             notify_saypose(executor, tprintf("%s %s \"%s\"",
00250                 Moniker(executor), saystring, message));
00251 #ifdef REALITY_LVLS
00252             notify_except_rlevel(loc, executor, executor, tprintf("%s %s \"%s\"", Moniker(executor), saystring, message), MSG_SAYPOSE);
00253 #else
00254             notify_except(loc, executor, executor, tprintf("%s %s \"%s\"", Moniker(executor), saystring, message), MSG_SAYPOSE);
00255 #endif
00256             free_lbuf(saystring);
00257         }
00258         else
00259         {
00260             notify_saypose(executor, tprintf("You say, \"%s\"", message));
00261 #ifdef REALITY_LVLS
00262             notify_except_rlevel(loc, executor, executor, tprintf("%s says, \"%s\"", Moniker(executor), message), MSG_SAYPOSE);
00263 #else
00264             notify_except(loc, executor, executor, tprintf("%s says, \"%s\"", Moniker(executor), message), MSG_SAYPOSE);
00265 #endif
00266         }
00267         break;
00268 
00269     case SAY_POSE:
00270 #ifdef REALITY_LVLS
00271         notify_except_rlevel(loc, executor, -1, tprintf("%s %s", Moniker(executor), message), MSG_SAYPOSE);
00272 #else
00273         notify_all_from_inside_saypose(loc, executor, tprintf("%s %s", Moniker(executor), message));
00274 #endif
00275         break;
00276 
00277     case SAY_POSE_NOSPC:
00278 #ifdef REALITY_LVLS
00279         notify_except_rlevel(loc, executor, -1, tprintf("%s%s", Moniker(executor), message), MSG_SAYPOSE);
00280 #else
00281         notify_all_from_inside_saypose(loc, executor, tprintf("%s%s", Moniker(executor), message));
00282 #endif
00283         break;
00284 
00285     case SAY_EMIT:
00286         if (  (say_flags & SAY_HERE)
00287            || (say_flags & SAY_HTML)
00288            || !say_flags)
00289         {
00290             if (say_flags & SAY_HTML)
00291             {
00292                 notify_all_from_inside_html(loc, executor, message);
00293             }
00294             else
00295             {
00296 
00297 #ifdef REALITY_LVLS
00298                 notify_except_rlevel(loc, executor, -1, message, SAY_EMIT);
00299 #else
00300                 notify_all_from_inside(loc, executor, message);
00301 #endif
00302             }
00303         }
00304         if (say_flags & SAY_ROOM)
00305         {
00306             if (  isRoom(loc)
00307                && (say_flags & SAY_HERE))
00308             {
00309                 if (messageNew)
00310                 {
00311                     free_lbuf(messageNew);
00312                 }
00313                 return;
00314             }
00315             for (depth = 0; !isRoom(loc) && (depth < 20); depth++)
00316             {
00317                 loc = Location(loc);
00318                 if (  !Good_obj(loc)
00319                    || (loc == Location(loc)))
00320                 {
00321                     if (messageNew)
00322                     {
00323                         free_lbuf(messageNew);
00324                     }
00325                     return;
00326                 }
00327             }
00328             if (isRoom(loc))
00329             {
00330 #ifdef REALITY_LVLS
00331                 notify_except_rlevel(loc, executor, -1, message, -1);
00332 #else
00333                 notify_all_from_inside(loc, executor, message);
00334 #endif
00335             }
00336         }
00337         break;
00338     }
00339     if (messageNew)
00340     {
00341         free_lbuf(messageNew);
00342     }
00343 }
00344 
00345 
00346 void do_shout(dbref executor, dbref caller, dbref enactor, int key,
00347     char *message)
00348 {
00349     UNUSED_PARAMETER(caller);
00350     UNUSED_PARAMETER(enactor);
00351 
00352     char *p;
00353     char *buf2, *bp;
00354     int say_flags = key & (SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
00355     key &= ~(SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
00356 
00357     // Parse speechmod if present.
00358     //
00359     char *messageNew = modSpeech(executor, message, true, "@wall");
00360     if (messageNew)
00361     {
00362         message = messageNew;
00363     }
00364 
00365     switch (key)
00366     {
00367     case SHOUT_SHOUT:
00368         switch (*message)
00369         {
00370         case ':':
00371             message[0] = ' ';
00372             say_shout(0, announce_msg, say_flags, executor, message);
00373             break;
00374 
00375         case ';':
00376             message++;
00377             say_shout(0, announce_msg, say_flags, executor, message);
00378             break;
00379 
00380         case '"':
00381             message++;
00382 
00383         default:
00384             buf2 = alloc_lbuf("do_shout.shout");
00385             bp = buf2;
00386             safe_str(" shouts, \"", buf2, &bp);
00387             safe_str(message, buf2, &bp);
00388             safe_chr('"', buf2, &bp);
00389             *bp = '\0';
00390             say_shout(0, announce_msg, say_flags, executor, buf2);
00391             free_lbuf(buf2);
00392         }
00393         STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
00394         log_name(executor);
00395         log_text(" shouts: ");
00396         log_text(message);
00397         ENDLOG;
00398         break;
00399 
00400     case SHOUT_WIZSHOUT:
00401         switch (*message)
00402         {
00403         case ':':
00404             message[0] = ' ';
00405             say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor,
00406                   message);
00407             break;
00408         case ';':
00409             message++;
00410             say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor,
00411                   message);
00412             break;
00413         case '"':
00414             message++;
00415         default:
00416             buf2 = alloc_lbuf("do_shout.wizshout");
00417             bp = buf2;
00418             safe_str(" says, \"", buf2, &bp);
00419             safe_str(message, buf2, &bp);
00420             safe_chr('"', buf2, &bp);
00421             *bp = '\0';
00422             say_shout(SHOUT_WIZARD, broadcast_msg, say_flags, executor, buf2);
00423             free_lbuf(buf2);
00424         }
00425         STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
00426         log_name(executor);
00427         log_text(" broadcasts: '");
00428         log_text(message);
00429         log_text("'");
00430         ENDLOG;
00431         break;
00432 
00433     case SHOUT_ADMINSHOUT:
00434         switch (*message)
00435         {
00436         case ':':
00437             message[0] = ' ';
00438             say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
00439                   message);
00440             break;
00441         case ';':
00442             message++;
00443             say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
00444                   message);
00445             break;
00446         case '"':
00447             message++;
00448         default:
00449             buf2 = alloc_lbuf("do_shout.adminshout");
00450             bp = buf2;
00451             safe_str(" says, \"", buf2, &bp);
00452             safe_str(message, buf2, &bp);
00453             safe_chr('"', buf2, &bp);
00454             *bp = '\0';
00455             say_shout(SHOUT_ADMIN, admin_msg, say_flags, executor,
00456                   buf2);
00457             free_lbuf(buf2);
00458         }
00459         STARTLOG(LOG_SHOUTS, "WIZ", "ASHOUT");
00460         log_name(executor);
00461         log_text(" yells: ");
00462         log_text(message);
00463         ENDLOG;
00464         break;
00465 
00466     case SHOUT_WALLPOSE:
00467         if (say_flags & SAY_NOTAG)
00468         {
00469             p = tprintf("%s %s", Moniker(executor), message);
00470         }
00471         else
00472         {
00473             p = tprintf("Announcement: %s %s", Moniker(executor),
00474                 message);
00475         }
00476         wall_broadcast(0, executor, p);
00477         STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
00478         log_name(executor);
00479         log_text(" WALLposes: ");
00480         log_text(message);
00481         ENDLOG;
00482         break;
00483 
00484     case SHOUT_WIZPOSE:
00485         if (say_flags & SAY_NOTAG)
00486         {
00487             p = tprintf("%s %s", Moniker(executor), message);
00488         }
00489         else
00490         {
00491             p = tprintf("Broadcast: %s %s", Moniker(executor), message);
00492         }
00493         wall_broadcast(SHOUT_WIZARD, executor, p);
00494         STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
00495         log_name(executor);
00496         log_text(" WIZposes: ");
00497         log_text(message);
00498         ENDLOG;
00499         break;
00500 
00501     case SHOUT_WALLEMIT:
00502         if (say_flags & SAY_NOTAG)
00503         {
00504             p = tprintf("%s", message);
00505         }
00506         else
00507         {
00508             p = tprintf("Announcement: %s", message);
00509         }
00510         wall_broadcast(0, executor, p);
00511         STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT");
00512         log_name(executor);
00513         log_text(" WALLemits: ");
00514         log_text(message);
00515         ENDLOG;
00516         break;
00517 
00518     case SHOUT_WIZEMIT:
00519         if (say_flags & SAY_NOTAG)
00520         {
00521             p = tprintf("%s", message);
00522         }
00523         else
00524         {
00525             p = tprintf("Broadcast: %s", message);
00526         }
00527         wall_broadcast(SHOUT_WIZARD, executor, p);
00528         STARTLOG(LOG_SHOUTS, "WIZ", "BCAST");
00529         log_name(executor);
00530         log_text(" WIZemit: ");
00531         log_text(message);
00532         ENDLOG;
00533         break;
00534     }
00535     if (messageNew)
00536     {
00537         free_lbuf(messageNew);
00538     }
00539 }
00540 
00541 /* ---------------------------------------------------------------------------
00542  * do_page: Handle the page command.
00543  * Page-pose code from shadow@prelude.cc.purdue.
00544  */
00545 
00546 static void page_return(dbref player, dbref target, const char *tag,
00547     int anum, const char *dflt)
00548 {
00549     if (MuxAlarm.bAlarmed)
00550     {
00551         return;
00552     }
00553 
00554     dbref aowner;
00555     int aflags;
00556     char *str, *str2, *buf, *bp;
00557 
00558     str = atr_pget(target, anum, &aowner, &aflags);
00559     if (*str)
00560     {
00561         str2 = bp = alloc_lbuf("page_return");
00562         buf = str;
00563         mux_exec(str2, &bp, target, player, player,
00564                  EV_FCHECK | EV_EVAL | EV_TOP | EV_NO_LOCATION, &buf,
00565                  (char **)NULL, 0);
00566         *bp = '\0';
00567         if (*str2)
00568         {
00569             CLinearTimeAbsolute ltaNow;
00570             ltaNow.GetLocal();
00571             FIELDEDTIME ft;
00572             ltaNow.ReturnFields(&ft);
00573 
00574             char *p = tprintf("%s message from %s: %s", tag,
00575                 Moniker(target), str2);
00576             notify_with_cause_ooc(player, target, p);
00577             p = tprintf("[%d:%02d] %s message sent to %s.", ft.iHour,
00578                 ft.iMinute, tag, Moniker(player));
00579             notify_with_cause_ooc(target, player, p);
00580         }
00581         free_lbuf(str2);
00582     }
00583     else if (dflt && *dflt)
00584     {
00585         notify_with_cause_ooc(player, target, dflt);
00586     }
00587     free_lbuf(str);
00588 }
00589 
00590 static bool page_check(dbref player, dbref target)
00591 {
00592     if (!payfor(player, Guest(player) ? 0 : mudconf.pagecost))
00593     {
00594         notify(player, tprintf("You don't have enough %s.", mudconf.many_coins));
00595     }
00596     else if (!Connected(target))
00597     {
00598         page_return(player, target, "Away", A_AWAY,
00599             tprintf("Sorry, %s is not connected.", Moniker(target)));
00600     }
00601     else if (!could_doit(player, target, A_LPAGE))
00602     {
00603         if (  Can_Hide(target)
00604            && Hidden(target)
00605            && !See_Hidden(player))
00606         {
00607             page_return(player, target, "Away", A_AWAY,
00608                 tprintf("Sorry, %s is not connected.", Moniker(target)));
00609         }
00610         else
00611         {
00612             page_return(player, target, "Reject", A_REJECT,
00613                 tprintf("Sorry, %s is not accepting pages.", Moniker(target)));
00614         }
00615     }
00616     else if (!could_doit(target, player, A_LPAGE))
00617     {
00618         char *p;
00619         if (Wizard(player))
00620         {
00621             p = tprintf("Warning: %s can't return your page.",
00622                 Moniker(target));
00623             notify(player, p);
00624             return true;
00625         }
00626         else
00627         {
00628             p = tprintf("Sorry, %s can't return your page.",
00629                 Moniker(target));
00630             notify(player, p);
00631             return false;
00632         }
00633     }
00634     else
00635     {
00636         return true;
00637     }
00638     return false;
00639 }
00640 
00641 // The combinations are:
00642 //
00643 //           nargs  arg1[0]  arg2[0]
00644 //   ''        1      '\0'    '\0'      Report LastPaged to player.
00645 //   'a'       1      'a'     '\0'      Page LastPaged with A
00646 //   'a='      2      'a'     '\0'      Page A. LastPaged <- A
00647 //   '=b'      2      '\0'    'b'       Page LastPaged with B
00648 //   'a=b'     2      'a'     'b'       Page A with B. LastPaged <- A
00649 //   'a=b1=[b2=]*...'                   All treated the same as 'a=b'.
00650 //
00651 void do_page
00652 (
00653     dbref executor,
00654     dbref caller,
00655     dbref enactor,
00656     int   key,
00657     int   nargs,
00658     char *arg1,
00659     char *arg2
00660 )
00661 {
00662     UNUSED_PARAMETER(caller);
00663     UNUSED_PARAMETER(enactor);
00664     UNUSED_PARAMETER(key);
00665 
00666     int   nPlayers = 0;
00667     dbref aPlayers[(LBUF_SIZE+1)/2];
00668 
00669     // Either we have been given a recipient list, or we are relying on an
00670     // existing A_LASTPAGE.
00671     //
00672     bool bModified = false;
00673     if (  nargs == 2
00674        && arg1[0] != '\0')
00675     {
00676         bModified = true;
00677 
00678         char *p = arg1;
00679         while (*p != '\0')
00680         {
00681             char *q = strchr(p, '"');
00682             if (q)
00683             {
00684                 *q = '\0';
00685             }
00686 
00687             // Decode space-delimited or comma-delimited recipients.
00688             //
00689             MUX_STRTOK_STATE tts;
00690             mux_strtok_src(&tts, p);
00691             mux_strtok_ctl(&tts, ", ");
00692             char *r;
00693             for (r = mux_strtok_parse(&tts); r; r = mux_strtok_parse(&tts))
00694             {
00695                 dbref target = lookup_player(executor, r, true);
00696                 if (target != NOTHING)
00697                 {
00698                     aPlayers[nPlayers++] = target;
00699                 }
00700                 else
00701                 {
00702                     notify(executor, tprintf("I don't recognize \"%s\".", r));
00703                 }
00704             }
00705 
00706             if (q)
00707             {
00708                 p = q + 1;
00709 
00710                 // Handle quoted named.
00711                 //
00712                 q = strchr(p, '"');
00713                 if (q)
00714                 {
00715                     *q = '\0';
00716                 }
00717 
00718                 dbref target = lookup_player(executor, p, true);
00719                 if (target != NOTHING)
00720                 {
00721                     aPlayers[nPlayers++] = target;
00722                 }
00723                 else
00724                 {
00725                     notify(executor, tprintf("I don't recognize \"%s\".", p));
00726                 }
00727 
00728                 if (q)
00729                 {
00730                     p = q + 1;
00731                 }
00732                 else
00733                 {
00734                     break;
00735                 }
00736             }
00737             else
00738             {
00739                 break;
00740             }
00741         }
00742     }
00743     else
00744     {
00745         // Need to decode the A_LASTPAGE.
00746         //
00747         dbref aowner;
00748         int   aflags;
00749         char *pLastPage = atr_get(executor, A_LASTPAGE, &aowner, &aflags);
00750 
00751         MUX_STRTOK_STATE tts;
00752         mux_strtok_src(&tts, pLastPage);
00753         mux_strtok_ctl(&tts, " ");
00754         char *p;
00755         for (p = mux_strtok_parse(&tts); p; p = mux_strtok_parse(&tts))
00756         {
00757             dbref target = mux_atol(p);
00758             if (  Good_obj(target)
00759                && isPlayer(target))
00760             {
00761                 aPlayers[nPlayers++] = target;
00762             }
00763             else
00764             {
00765                 notify(executor, tprintf("I don't recognize #%d.", target));
00766                 bModified = true;
00767             }
00768         }
00769         free_lbuf(pLastPage);
00770     }
00771 
00772     int nValid = nPlayers;
00773 
00774     // Remove duplicate dbrefs.
00775     //
00776     int i;
00777     for (i = 0; i < nPlayers-1; i++)
00778     {
00779         if (aPlayers[i] != NOTHING)
00780         {
00781             int j;
00782             for (j = i+1; j < nPlayers; j++)
00783             {
00784                 if (aPlayers[j] == aPlayers[i])
00785                 {
00786                     aPlayers[j] = NOTHING;
00787                     bModified = true;
00788                     nValid--;
00789                 }
00790             }
00791         }
00792     }
00793 
00794     // If we are doing more than reporting, we have some other dbref
00795     // validation to do.
00796     //
00797     if (  nargs == 2
00798        || arg1[0] != '\0')
00799     {
00800         for (i = 0; i < nPlayers; i++)
00801         {
00802             if (  Good_obj(aPlayers[i])
00803                && !page_check(executor, aPlayers[i]))
00804             {
00805                 aPlayers[i] = NOTHING;
00806                 bModified = true;
00807                 nValid--;
00808             }
00809         }
00810     }
00811 
00812     if (bModified)
00813     {
00814         // Our aPlayers could be different than the one encoded on A_LASTPAGE.
00815         // Update the database.
00816         //
00817         ITL itl;
00818         char *pBuff = alloc_lbuf("do_page.lastpage");
00819         char *pBufc = pBuff;
00820         ItemToList_Init(&itl, pBuff, &pBufc);
00821         for (i = 0; i < nPlayers; i++)
00822         {
00823             if (  Good_obj(aPlayers[i])
00824                && !ItemToList_AddInteger(&itl, aPlayers[i]))
00825             {
00826                 break;
00827             }
00828         }
00829         ItemToList_Final(&itl);
00830         atr_add_raw(executor, A_LASTPAGE, pBuff);
00831         free_lbuf(pBuff);
00832     }
00833 
00834     // Verify that the recipient list isn't empty.
00835     //
00836     if (nValid == 0)
00837     {
00838         if (  nargs == 1
00839            && arg1[0] == '\0')
00840         {
00841             notify(executor, "You have not paged anyone.");
00842         }
00843         else
00844         {
00845             notify(executor, "No one to page.");
00846         }
00847         return;
00848     }
00849 
00850     // Build a friendly representation of the recipient list.
00851     //
00852     char *aFriendly = alloc_lbuf("do_page.friendly");
00853     char *pFriendly = aFriendly;
00854 
00855     if (nValid > 1)
00856     {
00857         safe_chr('(', aFriendly, &pFriendly);
00858     }
00859     bool bFirst = true;
00860     for (i = 0; i < nPlayers; i++)
00861     {
00862         if (aPlayers[i] != NOTHING)
00863         {
00864             if (bFirst)
00865             {
00866                 bFirst = false;
00867             }
00868             else
00869             {
00870                 safe_copy_buf(", ", 2, aFriendly, &pFriendly);
00871             }
00872             safe_str(Moniker(aPlayers[i]), aFriendly, &pFriendly);
00873         }
00874     }
00875     if (nValid > 1)
00876     {
00877         safe_chr(')', aFriendly, &pFriendly);
00878     }
00879     *pFriendly = '\0';
00880 
00881     // We may be able to proceed directly to the reporting case.
00882     //
00883     if (  nargs == 1
00884        && arg1[0] == '\0')
00885     {
00886         notify(executor, tprintf("You last paged %s.", aFriendly));
00887         free_lbuf(aFriendly);
00888         return;
00889     }
00890 
00891     // Build messages.
00892     //
00893     char *omessage = alloc_lbuf("do_page.omessage");
00894     char *imessage = alloc_lbuf("do_page.imessage");
00895     char *omp = omessage;
00896     char *imp = imessage;
00897 
00898     char *pMessage;
00899     if (nargs == 1)
00900     {
00901         // 'page A' form.
00902         //
00903         pMessage = arg1;
00904     }
00905     else
00906     {
00907         // 'page A=', 'page =B', and 'page A=B' forms.
00908         //
00909         pMessage = arg2;
00910     }
00911 
00912     int pageMode;
00913     switch (*pMessage)
00914     {
00915     case '\0':
00916         pageMode = 1;
00917         break;
00918 
00919     case ':':
00920         pageMode = 2;
00921         pMessage++;
00922         break;
00923 
00924     case ';':
00925         pageMode = 3;
00926         pMessage++;
00927         break;
00928 
00929     case '"':
00930         pMessage++;
00931 
00932         // FALL THROUGH
00933 
00934     default:
00935         pageMode = 0;
00936     }
00937 
00938     char *newMessage = modSpeech(executor, pMessage, true, "page");
00939     if (newMessage)
00940     {
00941         pMessage = newMessage;
00942     }
00943 
00944     switch (pageMode)
00945     {
00946     case 1:
00947         // 'page A=' form.
00948         //
00949         if (nValid == 1)
00950         {
00951             safe_tprintf_str(omessage, &omp, "From afar, %s pages you.",
00952                 Moniker(executor));
00953         }
00954         else
00955         {
00956             safe_tprintf_str(omessage, &omp, "From afar, %s pages %s.",
00957                 Moniker(executor), aFriendly);
00958         }
00959         safe_tprintf_str(imessage, &imp, "You page %s.", aFriendly);
00960         break;
00961 
00962     case 2:
00963         safe_str("From afar, ", omessage, &omp);
00964         if (nValid > 1)
00965         {
00966             safe_tprintf_str(omessage, &omp, "to %s: ", aFriendly);
00967         }
00968         safe_tprintf_str(omessage, &omp, "%s %s", Moniker(executor), pMessage);
00969         safe_tprintf_str(imessage, &imp, "Long distance to %s: %s %s",
00970             aFriendly, Moniker(executor), pMessage);
00971         break;
00972 
00973     case 3:
00974         safe_str("From afar, ", omessage, &omp);
00975         if (nValid > 1)
00976         {
00977             safe_tprintf_str(omessage, &omp, "to %s: ", aFriendly);
00978         }
00979         safe_tprintf_str(omessage, &omp, "%s%s", Moniker(executor), pMessage);
00980         safe_tprintf_str(imessage, &imp, "Long distance to %s: %s%s",
00981             aFriendly, Moniker(executor), pMessage);
00982         break;
00983 
00984     default:
00985         if (nValid > 1)
00986         {
00987             safe_tprintf_str(omessage, &omp, "To %s, ", aFriendly);
00988         }
00989         safe_tprintf_str(omessage, &omp, "%s pages: %s", Moniker(executor),
00990             pMessage);
00991         safe_tprintf_str(imessage, &imp, "You paged %s with '%s'",
00992             aFriendly, pMessage);
00993         break;
00994     }
00995     free_lbuf(aFriendly);
00996 
00997     // Send message to recipients.
00998     //
00999     for (i = 0; i < nPlayers; i++)
01000     {
01001         dbref target = aPlayers[i];
01002         if (target != NOTHING)
01003         {
01004             notify_with_cause_ooc(target, executor, omessage);
01005             int target_idle = fetch_idle(target);
01006             int target_idle_timeout_val = idle_timeout_val(target);
01007             if (target_idle >= target_idle_timeout_val)
01008             {
01009                 page_return(executor, target, "Idle", A_IDLE, NULL);
01010             }
01011         }
01012     }
01013     free_lbuf(omessage);
01014 
01015     // Send message to sender.
01016     //
01017     notify(executor, imessage);
01018     free_lbuf(imessage);
01019     if (newMessage)
01020     {
01021         free_lbuf(newMessage);
01022     }
01023 }
01024 
01025 /* ---------------------------------------------------------------------------
01026  * do_pemit: Messages to specific players, or to all but specific players.
01027  */
01028 
01029 static void whisper_pose(dbref player, dbref target, char *message, bool bSpace)
01030 {
01031     char *newMessage = modSpeech(player, message, true, "whisper");
01032     if (newMessage)
01033     {
01034         message = newMessage;
01035     }
01036     char *buff = alloc_lbuf("do_pemit.whisper.pose");
01037     strcpy(buff, Moniker(player));
01038     notify(player, tprintf("%s senses \"%s%s%s\"", Moniker(target), buff,
01039         bSpace ? " " : "", message));
01040     notify_with_cause(target, player, tprintf("You sense %s%s%s", buff,
01041         bSpace ? " " : "", message));
01042     free_lbuf(buff);
01043     if (newMessage)
01044     {
01045         free_lbuf(newMessage);
01046     }
01047 }
01048 
01049 void do_pemit_single
01050 (
01051     dbref player,
01052     int key,
01053     bool bDoContents,
01054     int pemit_flags,
01055     char *recipient,
01056     int chPoseType,
01057     char *message
01058 )
01059 {
01060     dbref target, loc;
01061     char *buf2, *bp;
01062     int depth;
01063     bool ok_to_do = false;
01064 
01065     switch (key)
01066     {
01067     case PEMIT_FSAY:
01068     case PEMIT_FPOSE:
01069     case PEMIT_FPOSE_NS:
01070     case PEMIT_FEMIT:
01071         target = match_controlled(player, recipient);
01072         if (target == NOTHING)
01073         {
01074             return;
01075         }
01076         ok_to_do = true;
01077         break;
01078 
01079     default:
01080         init_match(player, recipient, TYPE_PLAYER);
01081         match_everything(0);
01082         target = match_result();
01083     }
01084 
01085     char *newMessage = NULL;
01086     char *saystring = NULL;
01087 
01088     char *p;
01089     switch (target)
01090     {
01091     case NOTHING:
01092         switch (key)
01093         {
01094         case PEMIT_WHISPER:
01095             notify(player, "Whisper to whom?");
01096             break;
01097 
01098         case PEMIT_PEMIT:
01099             notify(player, "Emit to whom?");
01100             break;
01101 
01102         case PEMIT_OEMIT:
01103             notify(player, "Emit except to whom?");
01104             break;
01105 
01106         default:
01107             notify(player, "Sorry.");
01108             break;
01109         }
01110         break;
01111 
01112     case AMBIGUOUS:
01113         notify(player, "I don't know who you mean!");
01114         break;
01115 
01116     default:
01117 
01118         // Enforce locality constraints.
01119         //
01120         if (  !ok_to_do
01121            && (  nearby(player, target)
01122               || Long_Fingers(player)
01123               || Controls(player, target)))
01124         {
01125             ok_to_do = true;
01126         }
01127         if (  !ok_to_do
01128            && key == PEMIT_PEMIT
01129            && isPlayer(target)
01130            && mudconf.pemit_players)
01131         {
01132             if (!page_check(player, target))
01133             {
01134                 return;
01135             }
01136             ok_to_do = true;
01137         }
01138         if (  !ok_to_do
01139            && (  !mudconf.pemit_any
01140               || key != PEMIT_PEMIT))
01141         {
01142             notify(player, "You are too far away to do that.");
01143             return;
01144         }
01145         if (  bDoContents
01146            && !Controls(player, target)
01147            && !mudconf.pemit_any)
01148         {
01149             notify(player, NOPERM_MESSAGE);
01150             return;
01151         }
01152         loc = where_is(target);
01153 
01154         switch (key)
01155         {
01156         case PEMIT_PEMIT:
01157             if (bDoContents)
01158             {
01159                 if (Has_contents(target))
01160                 {
01161                     notify_all_from_inside(target, player, message);
01162                 }
01163             }
01164             else
01165             {
01166                 if (pemit_flags & PEMIT_HTML)
01167                 {
01168                     notify_with_cause_html(target, player, message);
01169                 }
01170                 else
01171                 {
01172                     notify_with_cause(target, player, message);
01173                 }
01174             }
01175             break;
01176 
01177         case PEMIT_OEMIT:
01178             notify_except(Location(target), player, target, message, 0);
01179             break;
01180 
01181         case PEMIT_WHISPER:
01182             if (  isPlayer(target)
01183                && !Connected(target))
01184             {
01185                 page_return(player, target, "Away", A_AWAY,
01186                     tprintf("Sorry, %s is not connected.", Moniker(target)));
01187                 return;
01188             }
01189             switch (chPoseType)
01190             {
01191             case ':':
01192                 message++;
01193                 whisper_pose(player, target, message, true);
01194                 break;
01195 
01196             case ';':
01197                 message++;
01198                 whisper_pose(player, target, message, false);
01199                 break;
01200 
01201             case '"':
01202                 message++;
01203 
01204             default:
01205                 newMessage = modSpeech(player, message, true, "whisper");
01206                 if (newMessage)
01207                 {
01208                     message = newMessage;
01209                 }
01210                 notify(player, tprintf("You whisper \"%s\" to %s.", message,
01211                     Moniker(target)));
01212                 notify_with_cause(target, player,
01213                     tprintf("%s whispers \"%s\"", Moniker(player), message));
01214                 if (newMessage)
01215                 {
01216                     free_lbuf(newMessage);
01217                 }
01218             }
01219             if (  !mudconf.quiet_whisper
01220                && !Wizard(player))
01221             {
01222                 loc = where_is(player);
01223                 if (loc != NOTHING)
01224                 {
01225                     buf2 = alloc_lbuf("do_pemit.whisper.buzz");
01226                     bp = buf2;
01227                     safe_str(Moniker(player), buf2, &bp);
01228                     safe_str(" whispers something to ", buf2, &bp);
01229                     safe_str(Moniker(target), buf2, &bp);
01230                     *bp = '\0';
01231                     notify_except2(loc, player, player, target, buf2);
01232                     free_lbuf(buf2);
01233                 }
01234             }
01235             break;
01236 
01237         case PEMIT_FSAY:
01238             newMessage = modSpeech(target, message, true, "@fsay");
01239             if (newMessage)
01240             {
01241                 message = newMessage;
01242             }
01243             notify(target, tprintf("You say, \"%s\"", message));
01244             if (loc != NOTHING)
01245             {
01246                 saystring = modSpeech(target, message, false, "@fsay");
01247                 if (saystring)
01248                 {
01249                     p = tprintf("%s %s \"%s\"", Moniker(target),
01250                         saystring, message);
01251                     notify_except(loc, player, target, p, 0);
01252                 }
01253                 else
01254                 {
01255                     p = tprintf("%s says, \"%s\"", Moniker(target),
01256                         message);
01257                     notify_except(loc, player, target, p, 0);
01258                 }
01259             }
01260             if (saystring)
01261             {
01262                 free_lbuf(saystring);
01263             }
01264             if (newMessage)
01265             {
01266                 free_lbuf(newMessage);
01267             }
01268             break;
01269 
01270         case PEMIT_FPOSE:
01271             newMessage = modSpeech(target, message, true, "@fpose");
01272             if (newMessage)
01273             {
01274                 message = newMessage;
01275             }
01276             p = tprintf("%s %s", Moniker(target), message);
01277             notify_all_from_inside(loc, player, p);
01278             if (newMessage)
01279             {
01280                 free_lbuf(newMessage);
01281             }
01282             break;
01283 
01284         case PEMIT_FPOSE_NS:
01285             newMessage = modSpeech(target, message, true, "@fpose");
01286             if (newMessage)
01287             {
01288                 message = newMessage;
01289             }
01290             p = tprintf("%s%s", Moniker(target), message);
01291             notify_all_from_inside(loc, player, p);
01292             if (newMessage)
01293             {
01294                 free_lbuf(newMessage);
01295             }
01296             break;
01297 
01298         case PEMIT_FEMIT:
01299             if (  (pemit_flags & PEMIT_HERE)
01300                || !pemit_flags)
01301             {
01302                 notify_all_from_inside(loc, player, message);
01303             }
01304             if (pemit_flags & PEMIT_ROOM)
01305             {
01306                 if (  isRoom(loc)
01307                    && (pemit_flags & PEMIT_HERE))
01308                 {
01309                     return;
01310                 }
01311                 depth = 0;
01312                 while (  !isRoom(loc)
01313                       && depth++ < 20)
01314                 {
01315                     loc = Location(loc);
01316                     if (  loc == NOTHING
01317                        || loc == Location(loc))
01318                     {
01319                         return;
01320                     }
01321                 }
01322                 if (isRoom(loc))
01323                 {
01324                     notify_all_from_inside(loc, player, message);
01325                 }
01326             }
01327             break;
01328         }
01329     }
01330 }
01331 
01332 void do_pemit_list
01333 (
01334     dbref player,
01335     int key,
01336     bool bDoContents,
01337     int pemit_flags,
01338     char *list,
01339     int chPoseType,
01340     char *message
01341 )
01342 {
01343     // Send a message to a list of dbrefs. The list is destructively
01344     // modified.
01345     //
01346     if (  message[0] == '\0'
01347        || list[0] == '\0')
01348     {
01349         return;
01350     }
01351 
01352     char *p;
01353     MUX_STRTOK_STATE tts;
01354     mux_strtok_src(&tts, list);
01355     mux_strtok_ctl(&tts, " ");
01356     for (p = mux_strtok_parse(&tts); p; p = mux_strtok_parse(&tts))
01357     {
01358         do_pemit_single(player, key, bDoContents, pemit_flags, p, chPoseType,
01359             message);
01360     }
01361 }
01362 
01363 void do_pemit
01364 (
01365     dbref executor,
01366     dbref caller,
01367     dbref enactor,
01368     int   key,
01369     int   nargs,
01370     char *recipient,
01371     char *message
01372 )
01373 {
01374     UNUSED_PARAMETER(caller);
01375     UNUSED_PARAMETER(enactor);
01376 
01377     if (nargs < 2)
01378     {
01379         return;
01380     }
01381 
01382     // Decode PEMIT_CONENTS and PEMIT_LIST and remove from key.
01383     //
01384     bool bDoContents = false;
01385     if (key & PEMIT_CONTENTS)
01386     {
01387         bDoContents = true;
01388     }
01389     bool bDoList = false;
01390     if (key & PEMIT_LIST)
01391     {
01392         bDoList = true;
01393     }
01394     key &= ~(PEMIT_CONTENTS | PEMIT_LIST);
01395 
01396 
01397     // Decode PEMIT_HERE, PEMIT_ROOM, PEMIT_HTML and remove from key.
01398     //
01399     int mask = PEMIT_HERE | PEMIT_ROOM | PEMIT_HTML;
01400     int pemit_flags = key & mask;
01401     key &= ~mask;
01402 
01403     int chPoseType = *message;
01404     if (key == PEMIT_WHISPER && chPoseType == ':')
01405     {
01406         message[0] = ' ';
01407     }
01408 
01409     if (bDoList)
01410     {
01411         do_pemit_list(executor, key, bDoContents, pemit_flags, recipient,
01412             chPoseType, message);
01413     }
01414     else
01415     {
01416         do_pemit_single(executor, key, bDoContents, pemit_flags, recipient,
01417             chPoseType, message);
01418     }
01419 }

Generated on Mon May 28 04:40:11 2007 for MUX by  doxygen 1.4.7