mux/src/create.cpp

Go to the documentation of this file.
00001 // create.cpp -- Commands that create new objects.
00002 //
00003 // $Id: create.cpp,v 1.20 2006/01/31 00:17:26 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 "powers.h"
00014 
00015 // ---------------------------------------------------------------------------
00016 // parse_linkable_room: Get a location to link to.
00017 //
00018 static dbref parse_linkable_room(dbref player, char *room_name)
00019 {
00020     init_match(player, room_name, NOTYPE);
00021     match_everything(MAT_NO_EXITS | MAT_NUMERIC | MAT_HOME);
00022     dbref room = match_result();
00023 
00024     // HOME is always linkable
00025     //
00026     if (room == HOME)
00027     {
00028         return HOME;
00029     }
00030 
00031     // Make sure we can link to it
00032     //
00033     if (!Good_obj(room))
00034     {
00035         notify_quiet(player, "That's not a valid object.");
00036         return NOTHING;
00037     }
00038     else if (  !Has_contents(room)
00039             || !Linkable(player, room))
00040     {
00041         notify_quiet(player, "You can't link to that.");
00042         return NOTHING;
00043     }
00044     else
00045     {
00046         return room;
00047     }
00048 }
00049 
00050 // ---------------------------------------------------------------------------
00051 // open_exit, do_open: Open a new exit and optionally link it somewhere.
00052 //
00053 static void open_exit(dbref player, dbref loc, char *direction, char *linkto)
00054 {
00055     if (!Good_obj(loc))
00056     {
00057         return;
00058     }
00059     if (!direction || !*direction)
00060     {
00061         notify_quiet(player, "Open where?");
00062         return;
00063     }
00064     else if (!Controls(player, loc))
00065     {
00066         if(!(Open_ok(loc) && could_doit(player, loc, A_LOPEN)))
00067         {
00068             notify_quiet(player, NOPERM_MESSAGE);
00069             return;
00070         }
00071     }
00072     dbref exit = create_obj(player, TYPE_EXIT, direction, 0);
00073     if (exit == NOTHING)
00074     {
00075         return;
00076     }
00077 
00078     // Initialize everything and link it in.
00079     //
00080     s_Exits(exit, loc);
00081     s_Next(exit, Exits(loc));
00082     s_Exits(loc, exit);
00083     local_data_create(exit);
00084 
00085     // and we're done
00086     //
00087     notify_quiet(player, "Opened.");
00088 
00089     // See if we should do a link
00090     //
00091     if (!linkto || !*linkto)
00092     {
00093         return;
00094     }
00095 
00096     loc = parse_linkable_room(player, linkto);
00097     if (Good_obj(loc) || loc == HOME)
00098     {
00099         // Make sure the player passes the link lock
00100         //
00101         if (!could_doit(player, loc, A_LLINK))
00102         {
00103             notify_quiet(player, "You can't link to there.");
00104             return;
00105         }
00106 
00107         // Link it if the player can pay for it
00108         //
00109         if (!payfor(player, mudconf.linkcost))
00110         {
00111             notify_quiet(player,
00112                 tprintf("You don't have enough %s to link.",
00113                     mudconf.many_coins));
00114         }
00115         else
00116         {
00117             s_Location(exit, loc);
00118             notify_quiet(player, "Linked.");
00119         }
00120     }
00121 }
00122 
00123 void do_open(dbref executor, dbref caller, dbref enactor, int key,
00124              char *direction, char *links[], int nlinks)
00125 {
00126     UNUSED_PARAMETER(caller);
00127     UNUSED_PARAMETER(enactor);
00128 
00129     char *dest;
00130 
00131     // Create the exit and link to the destination, if there is one
00132     //
00133     if (nlinks >= 1)
00134     {
00135         dest = links[0];
00136     }
00137     else
00138     {
00139         dest = NULL;
00140     }
00141 
00142     dbref loc;
00143     if (key == OPEN_INVENTORY)
00144     {
00145         loc = executor;
00146     }
00147     else
00148     {
00149         loc = Location(executor);
00150     }
00151 
00152     open_exit(executor, loc, direction, dest);
00153 
00154     // Open the back link if we can.
00155     //
00156     if (nlinks >= 2)
00157     {
00158         dbref destnum = parse_linkable_room(executor, dest);
00159         if (Good_obj(destnum) || destnum == HOME)
00160         {
00161             char buff[12];
00162             mux_ltoa(loc, buff);
00163             open_exit(executor, destnum, links[1], buff);
00164         }
00165     }
00166 }
00167 
00168 // ---------------------------------------------------------------------------
00169 // link_exit, do_link: Set destination(exits), dropto(rooms) or
00170 // home(player,thing)
00171 
00172 static void link_exit(dbref player, dbref exit, dbref dest)
00173 {
00174     // Make sure we can link there
00175     //
00176     if (  dest != HOME
00177        && (  (  !Controls(player, dest)
00178              && !Link_ok(dest))
00179           || !could_doit(player, dest, A_LLINK)))
00180     {
00181         notify_quiet(player, NOPERM_MESSAGE);
00182         return;
00183     }
00184 
00185     // Exit must be unlinked or controlled by you
00186     //
00187     if (  Location(exit) != NOTHING
00188        && !Controls(player, exit))
00189     {
00190         notify_quiet(player, NOPERM_MESSAGE);
00191         return;
00192     }
00193 
00194     // Handle costs
00195     //
00196     int cost = mudconf.linkcost;
00197     int quot = 0;
00198     if (Owner(exit) != Owner(player))
00199     {
00200         cost += mudconf.opencost;
00201         quot += mudconf.exit_quota;
00202     }
00203     if (!canpayfees(player, player, cost, quot))
00204     {
00205         return;
00206     }
00207 
00208     // Pay the owner for his loss.
00209     //
00210     if (Owner(exit) != Owner(player))
00211     {
00212         giveto(Owner(exit), mudconf.opencost);
00213         add_quota(Owner(exit), quot);
00214         s_Owner(exit, Owner(player));
00215         db[exit].fs.word[FLAG_WORD1] &= ~(INHERIT | WIZARD);
00216         db[exit].fs.word[FLAG_WORD1] |= HALT;
00217     }
00218 
00219     // Link has been validated and paid for, do it and tell the player
00220     //
00221     s_Location(exit, dest);
00222     if (!Quiet(player))
00223     {
00224         notify_quiet(player, "Linked.");
00225     }
00226 }
00227 
00228 void do_link
00229 (
00230     dbref executor,
00231     dbref caller,
00232     dbref enactor,
00233     int   key,
00234     int   nargs,
00235     char *what,
00236     char *where
00237 )
00238 {
00239     UNUSED_PARAMETER(nargs);
00240 
00241     // Find the thing to link
00242     //
00243     init_match(executor, what, TYPE_EXIT);
00244     match_everything(0);
00245     dbref thing = noisy_match_result();
00246     if (thing == NOTHING)
00247     {
00248         return;
00249     }
00250 
00251     // Allow unlink if where is not specified
00252     //
00253     if (!where || !*where)
00254     {
00255         do_unlink(executor, caller, enactor, key, what);
00256         return;
00257     }
00258 
00259     dbref room;
00260     char *buff;
00261 
00262     switch (Typeof(thing))
00263     {
00264     case TYPE_EXIT:
00265 
00266         // Set destination
00267         //
00268         room = parse_linkable_room(executor, where);
00269         if (Good_obj(room) || room == HOME)
00270         {
00271             link_exit(executor, thing, room);
00272         }
00273         break;
00274 
00275     case TYPE_PLAYER:
00276     case TYPE_THING:
00277 
00278         // Set home.
00279         //
00280         if (!Controls(executor, thing))
00281         {
00282             notify_quiet(executor, NOPERM_MESSAGE);
00283             break;
00284         }
00285         init_match(executor, where, NOTYPE);
00286         match_everything(MAT_NO_EXITS);
00287         room = noisy_match_result();
00288         if (!Good_obj(room))
00289         {
00290             break;
00291         }
00292         if (!Has_contents(room))
00293         {
00294             notify_quiet(executor, "Can't link to an exit.");
00295             break;
00296         }
00297         if (  !can_set_home(executor, thing, room)
00298            || !could_doit(executor, room, A_LLINK))
00299         {
00300             notify_quiet(executor, NOPERM_MESSAGE);
00301         }
00302         else if (room == HOME)
00303         {
00304             notify_quiet(executor, "Can't set home to home.");
00305         }
00306         else
00307         {
00308             dbref nHomeOrig = Home(thing);
00309             dbref nHomeNew  = room;
00310             s_Home(thing, nHomeNew);
00311             if (!Quiet(executor))
00312             {
00313                 char *buff1 = alloc_lbuf("do_link.notify");
00314                 char *bp = buff1;
00315 
00316                 char *p;
00317                 p = tprintf("Home of %s(#%d) changed from ", Name(thing), thing);
00318                 safe_str(p, buff1, &bp);
00319                 p = tprintf("%s(#%d) to ", Name(nHomeOrig), nHomeOrig);
00320                 safe_str(p, buff1, &bp);
00321                 p = tprintf("%s(#%d).", Name(nHomeNew), nHomeNew);
00322                 safe_str(p, buff1, &bp);
00323                 *bp = '\0';
00324                 notify_quiet(executor, buff1);
00325                 free_lbuf(buff1);
00326             }
00327         }
00328         break;
00329 
00330     case TYPE_ROOM:
00331 
00332         // Set dropto.
00333         //
00334         if (!Controls(executor, thing))
00335         {
00336             notify_quiet(executor, NOPERM_MESSAGE);
00337             break;
00338         }
00339         room = parse_linkable_room(executor, where);
00340         if (  !Good_obj(room)
00341             && room != HOME)
00342         {
00343             break;
00344         }
00345 
00346         if (  room != HOME
00347            && !isRoom(room))
00348         {
00349             notify_quiet(executor, "That is not a room!");
00350         }
00351         else if (  room != HOME
00352                 && (  (  !Controls(executor, room)
00353                       && !Link_ok(room))
00354                    || !could_doit(executor, room, A_LLINK)))
00355         {
00356             notify_quiet(executor, NOPERM_MESSAGE);
00357         }
00358         else
00359         {
00360             dbref nDroptoOrig = Dropto(thing);
00361             dbref nDroptoNew  = room;
00362             s_Dropto(thing, room);
00363             if (!Quiet(executor))
00364             {
00365                 char *buff1 = alloc_lbuf("do_link2.notify");
00366                 char *bp = buff1;
00367 
00368                 char *p;
00369                 p = tprintf("Dropto of %s(#%d) changed from ", Name(thing), thing);
00370                 safe_str(p, buff1, &bp);
00371                 p = tprintf("%s(#%d) to ", Name(nDroptoOrig), nDroptoOrig);
00372                 safe_str(p, buff1, &bp);
00373                 p = tprintf("%s(#%d).", Name(nDroptoNew), nDroptoNew);
00374                 safe_str(p, buff1, &bp);
00375                 *bp = '\0';
00376                 notify_quiet(executor, buff1);
00377                 free_lbuf(buff1);
00378             }
00379         }
00380         break;
00381 
00382     case TYPE_GARBAGE:
00383 
00384         notify_quiet(executor, NOPERM_MESSAGE);
00385         break;
00386 
00387     default:
00388 
00389         STARTLOG(LOG_BUGS, "BUG", "OTYPE");
00390         buff = alloc_mbuf("do_link.LOG.badtype");
00391         sprintf(buff, "Strange object type: object #%d = %d",
00392             thing, Typeof(thing));
00393         log_text(buff);
00394         free_mbuf(buff);
00395         ENDLOG;
00396     }
00397 }
00398 
00399 // ---------------------------------------------------------------------------
00400 // do_parent: Set an object's parent field.
00401 //
00402 void do_parent
00403 (
00404     dbref executor,
00405     dbref caller,
00406     dbref enactor,
00407     int   key,
00408     int   nargs,
00409     char *tname,
00410     char *pname
00411 )
00412 {
00413     UNUSED_PARAMETER(caller);
00414     UNUSED_PARAMETER(enactor);
00415     UNUSED_PARAMETER(key);
00416     UNUSED_PARAMETER(nargs);
00417 
00418     dbref thing, parent, curr;
00419     int lev;
00420 
00421     // Get victim.
00422     //
00423     init_match(executor, tname, NOTYPE);
00424     match_everything(0);
00425     thing = noisy_match_result();
00426     if (!Good_obj(thing))
00427     {
00428         return;
00429     }
00430 
00431     // Make sure we can do it.
00432     //
00433     if (  Going(thing)
00434        || !Controls(executor, thing))
00435     {
00436         notify_quiet(executor, NOPERM_MESSAGE);
00437         return;
00438     }
00439 
00440     // Find out what the new parent is.
00441     //
00442     if (*pname)
00443     {
00444         init_match(executor, pname, Typeof(thing));
00445         match_everything(0);
00446         parent = noisy_match_result();
00447         if (!Good_obj(parent))
00448         {
00449             return;
00450         }
00451 
00452         // Make sure we have rights to set parent.
00453         //
00454         if (!Parentable(executor, parent))
00455         {
00456             notify_quiet(executor, NOPERM_MESSAGE);
00457             return;
00458         }
00459 
00460         // Verify no recursive reference
00461         //
00462         ITER_PARENTS(parent, curr, lev)
00463         {
00464             if (curr == thing)
00465             {
00466                 notify_quiet(executor, "You can't have yourself as a parent!");
00467                 return;
00468             }
00469         }
00470     }
00471     else
00472     {
00473         parent = NOTHING;
00474     }
00475 
00476     s_Parent(thing, parent);
00477     if (!Quiet(thing) && !Quiet(executor))
00478     {
00479         if (parent == NOTHING)
00480             notify_quiet(executor, "Parent cleared.");
00481         else
00482             notify_quiet(executor, "Parent set.");
00483     }
00484 }
00485 
00486 // ---------------------------------------------------------------------------
00487 // do_dig: Create a new room.
00488 //
00489 void do_dig(dbref executor, dbref caller, dbref enactor, int key, char *name,
00490             char *args[], int nargs)
00491 {
00492     UNUSED_PARAMETER(caller);
00493 
00494     // we don't need to know player's location!  hooray!
00495     //
00496     if (!name || !*name)
00497     {
00498         notify_quiet(executor, "Dig what?");
00499         return;
00500     }
00501     dbref room = create_obj(executor, TYPE_ROOM, name, 0);
00502     if (room == NOTHING)
00503     {
00504         return;
00505     }
00506 
00507     local_data_create(room);
00508     notify(executor, tprintf("%s created as room #%d.", name, room));
00509 
00510     char *buff = alloc_sbuf("do_dig");
00511     if (  nargs >= 1
00512        && args[0]
00513        && *args[0])
00514     {
00515         mux_ltoa(room, buff);
00516         open_exit(executor, Location(executor), args[0], buff);
00517     }
00518     if (  nargs >= 2
00519        && args[1]
00520        && *args[1])
00521     {
00522         mux_ltoa(Location(executor), buff);
00523         open_exit(executor, room, args[1], buff);
00524     }
00525     free_sbuf(buff);
00526     if (key == DIG_TELEPORT)
00527     {
00528         (void)move_via_teleport(executor, room, enactor, 0);
00529     }
00530 }
00531 
00532 // ---------------------------------------------------------------------------
00533 // do_create: Make a new object.
00534 //
00535 void do_create
00536 (
00537     dbref executor,
00538     dbref caller,
00539     dbref enactor,
00540     int   key,
00541     int   nargs,
00542     char *name,
00543     char *coststr
00544 )
00545 {
00546     UNUSED_PARAMETER(caller);
00547     UNUSED_PARAMETER(enactor);
00548     UNUSED_PARAMETER(key);
00549 
00550     int cost = 0;
00551     if (!name || !*name)
00552     {
00553         notify_quiet(executor, "Create what?");
00554         return;
00555     }
00556     else if (  nargs == 2
00557             && (cost = mux_atol(coststr)) < 0)
00558     {
00559         notify_quiet(executor, "You can't create an object for less than nothing!");
00560         return;
00561     }
00562     dbref thing = create_obj(executor, TYPE_THING, name, cost);
00563     if (thing == NOTHING)
00564     {
00565         return;
00566     }
00567 
00568     move_via_generic(thing, executor, NOTHING, 0);
00569     s_Home(thing, new_home(executor));
00570     if (!Quiet(executor))
00571     {
00572         notify(executor, tprintf("%s created as object #%d", Name(thing), thing));
00573     }
00574 
00575     local_data_create(thing);
00576 }
00577 
00578 
00579 // ---------------------------------------------------------------------------
00580 // do_clone: Create a copy of an object.
00581 //
00582 void do_clone
00583 (
00584     dbref executor,
00585     dbref caller,
00586     dbref enactor,
00587     int   key,
00588     int   nargs,
00589     char *name,
00590     char *arg2
00591 )
00592 {
00593     UNUSED_PARAMETER(caller);
00594     UNUSED_PARAMETER(enactor);
00595     UNUSED_PARAMETER(nargs);
00596 
00597     dbref clone, thing, new_owner, loc;
00598     FLAG rmv_flags;
00599     int cost;
00600 
00601     if ((key & CLONE_INVENTORY) || !Has_location(executor))
00602         loc = executor;
00603     else
00604         loc = Location(executor);
00605 
00606     if (!Good_obj(loc))
00607         return;
00608 
00609     init_match(executor, name, NOTYPE);
00610     match_everything(0);
00611     thing = noisy_match_result();
00612     if ((thing == NOTHING) || (thing == AMBIGUOUS))
00613     {
00614         return;
00615     }
00616 
00617     // Let players clone things set VISUAL. It's easier than retyping
00618     // in all that data.
00619     //
00620     if (!Examinable(executor, thing))
00621     {
00622         notify_quiet(executor, NOPERM_MESSAGE);
00623         return;
00624     }
00625     if (isPlayer(thing))
00626     {
00627         notify_quiet(executor, "You cannot clone players!");
00628         return;
00629     }
00630 
00631     // You can only make a parent link to what you control.
00632     //
00633     if (  !Controls(executor, thing)
00634        && !Parent_ok(thing)
00635        && (key & CLONE_FROM_PARENT))
00636     {
00637         notify_quiet(executor,
00638               tprintf("You don't control %s, ignoring /parent.",
00639                   Name(thing)));
00640         key &= ~CLONE_FROM_PARENT;
00641     }
00642 
00643     // Determine the cost of cloning
00644     //
00645     new_owner = (key & CLONE_PRESERVE) ? Owner(thing) : Owner(executor);
00646     if (key & CLONE_SET_COST)
00647     {
00648         cost = mux_atol(arg2);
00649         if (cost < mudconf.createmin)
00650             cost = mudconf.createmin;
00651         if (cost > mudconf.createmax)
00652             cost = mudconf.createmax;
00653         arg2 = NULL;
00654     }
00655     else
00656     {
00657         cost = 1;
00658         switch (Typeof(thing))
00659         {
00660         case TYPE_THING:
00661             cost = OBJECT_DEPOSIT((mudconf.clone_copy_cost) ?
00662                           Pennies(thing) : 1);
00663             break;
00664         case TYPE_ROOM:
00665             cost = mudconf.digcost;
00666             break;
00667         case TYPE_EXIT:
00668 
00669             if (!Controls(executor, loc))
00670             {
00671                 notify_quiet(executor, NOPERM_MESSAGE);
00672                 return;
00673             }
00674             cost = mudconf.digcost;
00675             break;
00676         }
00677     }
00678 
00679     // Go make the clone object.
00680     //
00681     bool bValid;
00682     int nValidName;
00683     char *pValidName = MakeCanonicalObjectName(arg2, &nValidName, &bValid);
00684     const char *clone_name;
00685     if (bValid)
00686     {
00687         clone_name = pValidName;
00688     }
00689     else
00690     {
00691         clone_name = Name(thing);
00692     }
00693     clone = create_obj(new_owner, Typeof(thing), clone_name, cost);
00694 
00695     if (clone == NOTHING)
00696     {
00697         return;
00698     }
00699 
00700     // Copy in the new data.
00701     //
00702     if (key & CLONE_FROM_PARENT)
00703     {
00704         s_Parent(clone, thing);
00705     }
00706     else
00707     {
00708         atr_cpy(clone, thing, false);
00709     }
00710 
00711     // Reset the name, since we cleared the attributes.
00712     //
00713     s_Name(clone, clone_name);
00714 
00715     // Reset the pennies, since it looks like we stamped on that, too.
00716     //
00717     s_Pennies(clone, OBJECT_ENDOWMENT(cost));
00718 
00719     // Clear out problem flags from the original
00720     //
00721     rmv_flags = WIZARD;
00722     if (!(key & CLONE_INHERIT) || !Inherits(executor))
00723     {
00724         rmv_flags |= INHERIT | IMMORTAL;
00725     }
00726     s_Flags(clone, FLAG_WORD1, Flags(thing) & ~rmv_flags);
00727 
00728     // Tell creator about it
00729     //
00730     if (!Quiet(executor))
00731     {
00732         if (arg2 && *arg2)
00733         {
00734             notify(executor,
00735              tprintf("%s cloned as %s, new copy is object #%d.",
00736                  Name(thing), arg2, clone));
00737         }
00738         else
00739         {
00740             notify(executor,
00741                    tprintf("%s cloned, new copy is object #%d.",
00742                        Name(thing), clone));
00743         }
00744     }
00745 
00746     // Put the new thing in its new home.  Break any dropto or link, then
00747     // try to re-establish it.
00748     //
00749     switch (Typeof(thing))
00750     {
00751     case TYPE_THING:
00752 
00753         s_Home(clone, clone_home(executor, thing));
00754         move_via_generic(clone, loc, executor, 0);
00755         break;
00756 
00757     case TYPE_ROOM:
00758 
00759         s_Dropto(clone, NOTHING);
00760         if (Dropto(thing) != NOTHING)
00761         {
00762             link_exit(executor, clone, Dropto(thing));
00763         }
00764         break;
00765 
00766     case TYPE_EXIT:
00767 
00768         s_Exits(loc, insert_first(Exits(loc), clone));
00769         s_Exits(clone, loc);
00770         s_Location(clone, NOTHING);
00771         if (Location(thing) != NOTHING)
00772         {
00773             link_exit(executor, clone, Location(thing));
00774         }
00775         break;
00776     }
00777 
00778     // If same owner run ACLONE, else halt it.  Also copy parent if we can.
00779     //
00780     if (new_owner == Owner(thing))
00781     {
00782         if (!(key & CLONE_FROM_PARENT))
00783         {
00784             s_Parent(clone, Parent(thing));
00785         }
00786         did_it(executor, clone, 0, NULL, 0, NULL, A_ACLONE,
00787                (char **)NULL, 0);
00788     }
00789     else
00790     {
00791         if (  !(key & CLONE_FROM_PARENT)
00792            && (Controls(executor, thing) || Parent_ok(thing)))
00793         {
00794             s_Parent(clone, Parent(thing));
00795         }
00796         s_Halted(clone);
00797     }
00798 
00799     local_data_clone(clone, thing);
00800 }
00801 
00802 // ---------------------------------------------------------------------------
00803 // do_pcreate: Create new players and robots.
00804 //
00805 void do_pcreate
00806 (
00807     dbref executor,
00808     dbref caller,
00809     dbref enactor,
00810     int   key,
00811     int   nargs,
00812     char *name,
00813     char *pass
00814 )
00815 {
00816     UNUSED_PARAMETER(caller);
00817     UNUSED_PARAMETER(enactor);
00818     UNUSED_PARAMETER(nargs);
00819 
00820     const char *pmsg;
00821     bool isrobot = (key == PCRE_ROBOT);
00822     dbref newplayer = create_player(name, pass, executor, isrobot, &pmsg);
00823     if (newplayer == NOTHING)
00824     {
00825         notify_quiet(executor, tprintf("Failure creating '%s'.  %s", name, pmsg));
00826         return;
00827     }
00828     AddToPublicChannel(newplayer);
00829     if (isrobot)
00830     {
00831         move_object(newplayer, Location(executor));
00832         notify_quiet(executor,
00833             tprintf("New robot '%s' (#%d) created with password '%s'",
00834                 name, newplayer, pass));
00835         notify_quiet(executor, "Your robot has arrived.");
00836         STARTLOG(LOG_PCREATES, "CRE", "ROBOT");
00837         log_name(newplayer);
00838         log_text(" created by ");
00839         log_name(executor);
00840         ENDLOG;
00841     }
00842     else
00843     {
00844         move_object(newplayer, mudconf.start_room);
00845         notify_quiet(executor,
00846                tprintf("New player '%s' (#%d) created with password '%s'",
00847                    name, newplayer, pass));
00848         STARTLOG(LOG_PCREATES | LOG_WIZARD, "WIZ", "PCREA");
00849         log_name(newplayer);
00850         log_text(" created by ");
00851         log_name(executor);
00852         ENDLOG;
00853 #ifdef GAME_DOOFERMUX
00854         // Added by D.Piper (del@doofer.org) 2000-APR
00855         //
00856         atr_add_raw(newplayer, A_REGINFO, "*Requires Registration*");
00857 #endif
00858     }
00859 }
00860 
00861 // ---------------------------------------------------------------------------
00862 // destroyable: Indicates if target of a @destroy is a 'special' object in
00863 // the database.
00864 //
00865 static bool destroyable(dbref victim)
00866 {
00867     if (  (victim == mudconf.default_home)
00868        || (victim == mudconf.start_home)
00869        || (victim == mudconf.start_room)
00870        || (victim == mudconf.master_room)
00871        || (victim == (dbref) 0)
00872        || (God(victim)))
00873     {
00874         return false;
00875     }
00876     return true;
00877 }
00878 
00879 // ---------------------------------------------------------------------------
00880 // can_destroy_player, do_destroy: Destroy things.
00881 //
00882 static bool can_destroy_player(dbref player, dbref victim)
00883 {
00884     if (!Wizard(player))
00885     {
00886         notify_quiet(player, "Sorry, no suicide allowed.");
00887         return false;
00888     }
00889     if (Wizard(victim))
00890     {
00891         notify_quiet(player, "Even you can't do that!");
00892         return false;
00893     }
00894     return true;
00895 }
00896 
00897 void do_destroy(dbref executor, dbref caller, dbref enactor, int key, char *what)
00898 {
00899     UNUSED_PARAMETER(caller);
00900     UNUSED_PARAMETER(enactor);
00901 
00902     // You can destroy anything you control.
00903     //
00904     dbref thing = match_controlled_quiet(executor, what);
00905 
00906     // If you own a location, you can destroy its exits.
00907     //
00908     if (  thing == NOTHING
00909        && Controls(executor, Location(executor)))
00910     {
00911         init_match(executor, what, TYPE_EXIT);
00912         match_exit();
00913         thing = last_match_result();
00914     }
00915 
00916     // You may destroy DESTROY_OK things in your inventory.
00917     //
00918     if (thing == NOTHING)
00919     {
00920         init_match(executor, what, TYPE_THING);
00921         match_possession();
00922         thing = last_match_result();
00923         if ( thing != NOTHING
00924            && !(isThing(thing) && Destroy_ok(thing)))
00925         {
00926             thing = NOPERM;
00927         }
00928     }
00929 
00930     // Return an error if we didn't find anything to destroy.
00931     //
00932     if (match_status(executor, thing) == NOTHING)
00933     {
00934         return;
00935     }
00936 
00937     // Check SAFE and DESTROY_OK flags.
00938     //
00939     if (  Safe(thing, executor)
00940        && !(key & DEST_OVERRIDE)
00941        && !(isThing(thing) && Destroy_ok(thing)))
00942     {
00943         notify_quiet(executor, "Sorry, that object is protected.  Use @destroy/override to destroy it.");
00944         return;
00945     }
00946 
00947     // Make sure we're not trying to destroy a special object.
00948     //
00949     if (!destroyable(thing))
00950     {
00951         notify_quiet(executor, "You can't destroy that!");
00952         return;
00953     }
00954 
00955     // Make sure we can do it, on a type-specific basis.
00956     //
00957     if(  isPlayer(thing)
00958       && !can_destroy_player(executor, thing))
00959     {
00960         return;
00961     }
00962 
00963     char *NameOfType = alloc_sbuf("do_destroy.NameOfType");
00964     strcpy(NameOfType, object_types[Typeof(thing)].name);
00965     mux_strlwr(NameOfType);
00966     if (Going(thing))
00967     {
00968         if (!mudconf.destroy_going_now)
00969         {
00970             notify_quiet(executor, tprintf("No sense beating a dead %s.", NameOfType));
00971             free_sbuf(NameOfType);
00972             return;
00973         }
00974         key |= DEST_INSTANT;
00975     }
00976 
00977     // Check whether we should perform instant destruction.
00978     //
00979     dbref ThingOwner = Owner(thing);
00980     bool bInstant = (key & DEST_INSTANT) || Destroy_ok(thing) || Destroy_ok(ThingOwner);
00981 
00982     if (!bInstant)
00983     {
00984         // Pre-destruction 'crumble' emits and one last possible showstopper.
00985         //
00986         switch (Typeof(thing))
00987         {
00988         case TYPE_ROOM:
00989             notify_all(thing, executor, "The room shakes and begins to crumble.");
00990             break;
00991 
00992         case TYPE_PLAYER:
00993             atr_add_raw(thing, A_DESTROYER, mux_ltoa_t(executor));
00994             if (!atr_get_raw(thing, A_DESTROYER))
00995             {
00996                 // Not a likely situation, but the player has too many
00997                 // attributes to remember it's destroyer, so we we need to
00998                 // take care of this more immediately.
00999                 //
01000                 bInstant = true;
01001                 notify(executor, "Player has a lot of attributes. Performing destruction immediately.");
01002                 break;
01003             }
01004 
01005             // FALL THROUGH
01006 
01007         case TYPE_EXIT:
01008         case TYPE_THING:
01009             notify(executor, tprintf("The %s shakes and begins to crumble.",
01010                 NameOfType));
01011             break;
01012 
01013         default:
01014             notify(executor, "Weird object type cannot be destroyed.");
01015             free_sbuf(NameOfType);
01016             return;
01017         }
01018 
01019         if (  !bInstant
01020            && !Quiet(thing)
01021            && !Quiet(ThingOwner))
01022         {
01023             notify_quiet(ThingOwner,
01024                 tprintf("You will be rewarded shortly for %s(#%d).",
01025                 Moniker(thing), thing));
01026         }
01027     }
01028     free_sbuf(NameOfType);
01029 
01030     // Imperative Destruction emits.
01031     //
01032     if (!Quiet(executor))
01033     {
01034         if (Good_owner(ThingOwner))
01035         {
01036             if (ThingOwner == Owner(executor))
01037             {
01038                 if (!Quiet(thing))
01039                 {
01040                     notify(executor, tprintf("Destroyed %s(#%d).",
01041                         Moniker(thing), thing));
01042                 }
01043             }
01044             else if (ThingOwner == thing)
01045             {
01046                 notify(executor, tprintf("Destroyed %s(#%d).",
01047                     Moniker(thing), thing));
01048             }
01049             else
01050             {
01051                 char *tname = alloc_lbuf("destroy_obj");
01052                 strcpy(tname, Moniker(ThingOwner));
01053                 notify(executor, tprintf("Destroyed %s's %s(#%d).",
01054                     tname, Moniker(thing), thing));
01055                 free_lbuf(tname);
01056             }
01057         }
01058     }
01059 
01060     if (bInstant)
01061     {
01062         // Instant destruction by type.
01063         //
01064         switch (Typeof(thing))
01065         {
01066         case TYPE_EXIT:
01067             destroy_exit(thing);
01068             break;
01069 
01070         case TYPE_PLAYER:
01071             destroy_player(executor, thing);
01072             break;
01073 
01074         case TYPE_ROOM:
01075             empty_obj(thing);
01076             destroy_obj(thing);
01077             break;
01078 
01079         case TYPE_THING:
01080             destroy_thing(thing);
01081             break;
01082 
01083         default:
01084             notify(executor, "Weird object type cannot be destroyed.");
01085             return;
01086         }
01087     }
01088     s_Going(thing);
01089 }

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