00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "config.h"
00007
00008 #include "mudconf.h"
00009 #include "config.h"
00010 #include "db.h"
00011 #include "interface.h"
00012 #include "externs.h"
00013 #include "match.h"
00014 #include "command.h"
00015 #include "alloc.h"
00016 #include "attrs.h"
00017 #include "powers.h"
00018
00019
00020
00021
00022
00023
00024 static dbref parse_linkable_room(dbref player, char *room_name)
00025 {
00026 dbref room;
00027
00028 init_match(player, room_name, NOTYPE);
00029 match_everything(MAT_NO_EXITS | MAT_NUMERIC | MAT_HOME);
00030 room = match_result();
00031
00032
00033
00034
00035
00036 if(room == HOME)
00037 return HOME;
00038
00039
00040
00041
00042
00043 if(!Good_obj(room)) {
00044 notify_quiet(player, "That's not a valid object.");
00045 return NOTHING;
00046 } else if(!Has_contents(room) || !Linkable(player, room)) {
00047 notify_quiet(player, "You can't link to that.");
00048 return NOTHING;
00049 } else {
00050 return room;
00051 }
00052 }
00053
00054
00055
00056
00057
00058
00059 static void open_exit(dbref player, dbref loc, char *direction, char *linkto)
00060 {
00061 dbref exit;
00062
00063 if(!Good_obj(loc))
00064 return;
00065
00066 if(!direction || !*direction) {
00067 notify_quiet(player, "Open where?");
00068 return;
00069 } else if(!controls(player, loc)) {
00070 notify_quiet(player, "Permission denied.");
00071 return;
00072 }
00073 exit = create_obj(player, TYPE_EXIT, direction, 0);
00074 if(exit == NOTHING)
00075 return;
00076
00077
00078
00079
00080
00081 s_Exits(exit, loc);
00082 s_Next(exit, Exits(loc));
00083 s_Exits(loc, exit);
00084
00085
00086
00087
00088
00089 notify_quiet(player, "Opened.");
00090
00091
00092
00093
00094
00095 if(!linkto || !*linkto)
00096 return;
00097
00098 loc = parse_linkable_room(player, linkto);
00099 if(loc != NOTHING) {
00100
00101
00102
00103
00104
00105 if(!could_doit(player, loc, A_LLINK)) {
00106 notify_quiet(player, "You can't link to there.");
00107 return;
00108 }
00109
00110
00111
00112
00113 if(!payfor(player, mudconf.linkcost)) {
00114 notify_quiet(player,
00115 tprintf("You don't have enough %s to link.",
00116 mudconf.many_coins));
00117 } else {
00118 s_Location(exit, loc);
00119 notify_quiet(player, "Linked.");
00120 }
00121 }
00122 }
00123
00124 void do_open(dbref player, dbref cause, int key, char *direction,
00125 char *links[], int nlinks)
00126 {
00127 dbref loc, destnum;
00128 char *dest;
00129
00130
00131
00132
00133
00134 if(nlinks >= 1)
00135 dest = links[0];
00136 else
00137 dest = NULL;
00138
00139 if(key == OPEN_INVENTORY)
00140 loc = player;
00141 else
00142 loc = Location(player);
00143
00144 open_exit(player, loc, direction, dest);
00145
00146
00147
00148
00149
00150 if(nlinks >= 2) {
00151 destnum = parse_linkable_room(player, dest);
00152 if(destnum != NOTHING) {
00153 open_exit(player, destnum, links[1], tprintf("%d", loc));
00154 }
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163
00164 static void link_exit(dbref player, dbref exit, dbref dest)
00165 {
00166 int cost, quot;
00167
00168
00169
00170
00171
00172 if((dest != HOME) && ((!controls(player, dest) && !Link_ok(dest)) ||
00173 !could_doit(player, dest, A_LLINK))) {
00174 notify_quiet(player, "Permission denied.");
00175 return;
00176 }
00177
00178
00179
00180
00181 if((Location(exit) != NOTHING) && !controls(player, exit)) {
00182 notify_quiet(player, "Permission denied.");
00183 return;
00184 }
00185
00186
00187
00188
00189 cost = mudconf.linkcost;
00190 quot = 0;
00191 if(Owner(exit) != Owner(player)) {
00192 cost += mudconf.opencost;
00193 quot += mudconf.exit_quota;
00194 }
00195 if(!canpayfees(player, player, cost, quot))
00196 return;
00197
00198
00199
00200
00201
00202 if(Owner(exit) != Owner(player)) {
00203 giveto(Owner(exit), mudconf.opencost);
00204 add_quota(Owner(exit), quot);
00205 s_Owner(exit, Owner(player));
00206 s_Flags(exit, (Flags(exit) & ~(INHERIT | WIZARD)) | HALT);
00207 }
00208
00209
00210
00211
00212 s_Location(exit, dest);
00213 if(!Quiet(player))
00214 notify_quiet(player, "Linked.");
00215 }
00216
00217 void do_link(dbref player, dbref cause, int key, char *what, char *where)
00218 {
00219 dbref thing, room;
00220 char *buff;
00221
00222
00223
00224
00225
00226 init_match(player, what, TYPE_EXIT);
00227 match_everything(0);
00228 thing = noisy_match_result();
00229 if(thing == NOTHING)
00230 return;
00231
00232
00233
00234
00235
00236 if(!where || !*where) {
00237 do_unlink(player, cause, key, what);
00238 return;
00239 }
00240 switch (Typeof(thing)) {
00241 case TYPE_EXIT:
00242
00243
00244
00245
00246
00247 room = parse_linkable_room(player, where);
00248 if(room != NOTHING)
00249 link_exit(player, thing, room);
00250 break;
00251 case TYPE_PLAYER:
00252 case TYPE_THING:
00253
00254
00255
00256
00257
00258 if(!Controls(player, thing)) {
00259 notify_quiet(player, "Permission denied.");
00260 break;
00261 }
00262 init_match(player, where, NOTYPE);
00263 match_everything(MAT_NO_EXITS);
00264 room = noisy_match_result();
00265 if(!Good_obj(room))
00266 break;
00267 if(!Has_contents(room)) {
00268 notify_quiet(player, "Can't link to an exit.");
00269 break;
00270 }
00271 if(!can_set_home(player, thing, room) ||
00272 !could_doit(player, room, A_LLINK)) {
00273 notify_quiet(player, "Permission denied.");
00274 } else if(room == HOME) {
00275 notify_quiet(player, "Can't set home to home.");
00276 } else {
00277 s_Home(thing, room);
00278 if(!Quiet(player))
00279 notify_quiet(player, "Home set.");
00280 }
00281 break;
00282 case TYPE_ROOM:
00283
00284
00285
00286
00287
00288 if(!Controls(player, thing)) {
00289 notify_quiet(player, "Permission denied.");
00290 break;
00291 }
00292 room = parse_linkable_room(player, where);
00293 if(!(Good_obj(room) || (room == HOME)))
00294 break;
00295
00296 if((room != HOME) && !isRoom(room)) {
00297 notify_quiet(player, "That is not a room!");
00298 } else if((room != HOME) && ((!controls(player, room) &&
00299 !Link_ok(room)) ||
00300 !could_doit(player, room, A_LLINK))) {
00301 notify_quiet(player, "Permission denied.");
00302 } else {
00303 s_Dropto(thing, room);
00304 if(!Quiet(player))
00305 notify_quiet(player, "Dropto set.");
00306 }
00307 break;
00308 case TYPE_GARBAGE:
00309 notify_quiet(player, "Permission denied.");
00310 break;
00311 default:
00312 log_error(LOG_BUGS, "BUG", "OTYPE", "Strange object type: object #%d = %d",
00313 thing, Typeof(thing));
00314 }
00315 }
00316
00317
00318
00319
00320
00321
00322 void do_parent(dbref player, dbref cause, int key, char *tname, char *pname)
00323 {
00324 dbref thing, parent, curr;
00325 int lev;
00326
00327
00328
00329
00330
00331 init_match(player, tname, NOTYPE);
00332 match_everything(0);
00333 thing = noisy_match_result();
00334 if(thing == NOTHING)
00335 return;
00336
00337
00338
00339
00340
00341 if(!Controls(player, thing)) {
00342 notify_quiet(player, "Permission denied.");
00343 return;
00344 }
00345
00346
00347
00348
00349 if(*pname) {
00350 init_match(player, pname, Typeof(thing));
00351 match_everything(0);
00352 parent = noisy_match_result();
00353 if(parent == NOTHING)
00354 return;
00355
00356
00357
00358
00359
00360 if(!Parentable(player, parent)) {
00361 notify_quiet(player, "Permission denied.");
00362 return;
00363 }
00364
00365
00366
00367
00368 ITER_PARENTS(parent, curr, lev) {
00369 if(curr == thing) {
00370 notify_quiet(player, "You can't have yourself as a parent!");
00371 return;
00372 }
00373 }
00374 } else {
00375 parent = NOTHING;
00376 }
00377
00378 s_Parent(thing, parent);
00379 if(!Quiet(thing) && !Quiet(player)) {
00380 if(parent == NOTHING)
00381 notify_quiet(player, "Parent cleared.");
00382 else
00383 notify_quiet(player, "Parent set.");
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392 void do_dig(dbref player, dbref cause, int key, char *name, char *args[],
00393 int nargs)
00394 {
00395 dbref room;
00396 char *buff;
00397
00398
00399
00400
00401
00402 if(!name || !*name) {
00403 notify_quiet(player, "Dig what?");
00404 return;
00405 }
00406 room = create_obj(player, TYPE_ROOM, name, 0);
00407 if(room == NOTHING)
00408 return;
00409
00410 notify_printf(player, "%s created with room number %d.", name, room);
00411
00412 buff = alloc_sbuf("do_dig");
00413 if((nargs >= 1) && args[0] && *args[0]) {
00414 sprintf(buff, "%d", room);
00415 open_exit(player, Location(player), args[0], buff);
00416 }
00417 if((nargs >= 2) && args[1] && *args[1]) {
00418 sprintf(buff, "%d", Location(player));
00419 open_exit(player, room, args[1], buff);
00420 }
00421 free_sbuf(buff);
00422 if(key == DIG_TELEPORT)
00423 (void) move_via_teleport(player, room, cause, 0);
00424 }
00425
00426
00427
00428
00429
00430
00431 void do_create(dbref player, dbref cause, int key, char *name, char *coststr)
00432 {
00433 dbref thing;
00434 int cost;
00435 char clearbuffer[MBUF_SIZE];
00436
00437 cost = atoi(coststr);
00438 strip_ansi_r(clearbuffer, name, MBUF_SIZE);
00439 if(!name || !*name || (strlen(clearbuffer) == 0)) {
00440 notify_quiet(player, "Create what?");
00441 return;
00442 } else if(cost < 0) {
00443 notify_quiet(player,
00444 "You can't create an object for less than nothing!");
00445 return;
00446 }
00447 thing = create_obj(player, TYPE_THING, name, cost);
00448 if(thing == NOTHING)
00449 return;
00450
00451 move_via_generic(thing, player, NOTHING, 0);
00452 s_Home(thing, new_home(player));
00453 if(!Quiet(player)) {
00454 notify_printf(player, "%s created as object #%d", Name(thing), thing);
00455 }
00456 }
00457
00458
00459
00460
00461
00462
00463 void do_clone(dbref player, dbref cause, int key, char *name, char *arg2)
00464 {
00465 dbref clone, thing, new_owner, loc;
00466 FLAG rmv_flags;
00467 int cost;
00468
00469 if((key & CLONE_INVENTORY) || !Has_location(player))
00470 loc = player;
00471 else
00472 loc = Location(player);
00473
00474 if(!Good_obj(loc))
00475 return;
00476
00477 init_match(player, name, NOTYPE);
00478 match_everything(0);
00479 thing = noisy_match_result();
00480 if((thing == NOTHING) || (thing == AMBIGUOUS))
00481 return;
00482
00483
00484
00485
00486
00487
00488 if(!Examinable(player, thing)) {
00489 notify_quiet(player, "Permission denied.");
00490 return;
00491 }
00492 if(isPlayer(thing)) {
00493 notify_quiet(player, "You cannot clone players!");
00494 return;
00495 }
00496
00497
00498
00499
00500 if(!Controls(player, thing) && !Parent_ok(thing) && (key & CLONE_PARENT)) {
00501 notify_quiet(player,
00502 tprintf("You don't control %s, ignoring /parent.",
00503 Name(thing)));
00504 key &= ~CLONE_PARENT;
00505 }
00506
00507
00508
00509
00510 new_owner = (key & CLONE_PRESERVE) ? Owner(thing) : Owner(player);
00511 if(key & CLONE_SET_COST) {
00512 cost = atoi(arg2);
00513 if(cost < mudconf.createmin)
00514 cost = mudconf.createmin;
00515 if(cost > mudconf.createmax)
00516 cost = mudconf.createmax;
00517 arg2 = NULL;
00518 } else {
00519 cost = 1;
00520 switch (Typeof(thing)) {
00521 case TYPE_THING:
00522 cost =
00523 OBJECT_DEPOSIT((mudconf.
00524 clone_copy_cost) ? Pennies(thing) : 1);
00525 break;
00526 case TYPE_ROOM:
00527 cost = mudconf.digcost;
00528 break;
00529 case TYPE_EXIT:
00530 if(!Controls(player, loc)) {
00531 notify_quiet(player, "Permission denied.");
00532 return;
00533 }
00534 cost = mudconf.digcost;
00535 break;
00536 }
00537 }
00538
00539
00540
00541
00542
00543 if((arg2 && *arg2) && ok_name(arg2))
00544 clone = create_obj(new_owner, Typeof(thing), arg2, cost);
00545 else
00546 clone = create_obj(new_owner, Typeof(thing), Name(thing), cost);
00547 if(clone == NOTHING)
00548 return;
00549
00550
00551
00552
00553
00554 atr_free(clone);
00555 if(key & CLONE_PARENT)
00556 s_Parent(clone, thing);
00557 else
00558 atr_cpy(player, clone, thing);
00559
00560
00561
00562
00563
00564 if((arg2 && *arg2) && ok_name(arg2))
00565 s_Name(clone, arg2);
00566 else
00567 s_Name(clone, Name(thing));
00568
00569
00570
00571
00572
00573 rmv_flags = WIZARD;
00574 if(!(key & CLONE_INHERIT) || (!Inherits(player)))
00575 rmv_flags |= INHERIT | IMMORTAL;
00576 s_Flags(clone, Flags(thing) & ~rmv_flags);
00577
00578
00579
00580
00581
00582 if(!Quiet(player)) {
00583 if(arg2 && *arg2)
00584 notify_printf(player,
00585 "%s cloned as %s, new copy is object #%d.",
00586 Name(thing), arg2, clone);
00587 else
00588 notify_printf(player, "%s cloned, new copy is object #%d.",
00589 Name(thing), clone);
00590 }
00591
00592
00593
00594
00595
00596 switch (Typeof(thing)) {
00597 case TYPE_THING:
00598 s_Home(clone, clone_home(player, thing));
00599 move_via_generic(clone, loc, player, 0);
00600 break;
00601 case TYPE_ROOM:
00602 s_Dropto(clone, NOTHING);
00603 if(Dropto(thing) != NOTHING)
00604 link_exit(player, clone, Dropto(thing));
00605 break;
00606 case TYPE_EXIT:
00607 s_Exits(loc, insert_first(Exits(loc), clone));
00608 s_Exits(clone, loc);
00609 s_Location(clone, NOTHING);
00610 if(Location(thing) != NOTHING)
00611 link_exit(player, clone, Location(thing));
00612 break;
00613 }
00614
00615
00616
00617
00618
00619
00620 if(new_owner == Owner(thing)) {
00621 if(!(key & CLONE_PARENT))
00622 s_Parent(clone, Parent(thing));
00623 did_it(player, clone, 0, NULL, 0, NULL, A_ACLONE, (char **) NULL, 0);
00624 } else {
00625 if(!(key & CLONE_PARENT) && (Controls(player, thing) ||
00626 Parent_ok(thing)))
00627 s_Parent(clone, Parent(thing));
00628 s_Halted(clone);
00629 }
00630 }
00631
00632
00633
00634
00635
00636
00637 void do_pcreate(dbref player, dbref cause, int key, char *name, char *pass)
00638 {
00639 int isrobot;
00640 dbref newplayer;
00641
00642 isrobot = (key == PCRE_ROBOT) ? 1 : 0;
00643 newplayer = create_player(name, pass, player, isrobot, 0);
00644 if(newplayer == NOTHING) {
00645 notify_quiet(player, tprintf("Failure creating '%s'", name));
00646 return;
00647 }
00648 if(isrobot) {
00649 move_object(newplayer, Location(player));
00650 notify_quiet(player,
00651 tprintf
00652 ("New robot '%s' (#%d) created with password '%s'", name,
00653 newplayer, pass));
00654
00655 notify_quiet(player, "Your robot has arrived.");
00656 STARTLOG(LOG_PCREATES, "CRE", "ROBOT") {
00657 log_name(newplayer);
00658 log_text((char *) " created by ");
00659 log_name(player);
00660 ENDLOG;
00661 }} else {
00662 move_object(newplayer, mudconf.start_room);
00663 notify_quiet(player,
00664 tprintf
00665 ("New player '%s' (#%d) created with password '%s'",
00666 name, newplayer, pass));
00667
00668 STARTLOG(LOG_PCREATES | LOG_WIZARD, "WIZ", "PCREA") {
00669 log_name(newplayer);
00670 log_text((char *) " created by ");
00671 log_name(player);
00672 ENDLOG;
00673 }}
00674 }
00675
00676
00677
00678
00679
00680
00681
00682 static int can_destroy_exit(dbref player, dbref exit)
00683 {
00684 dbref loc;
00685
00686 loc = Exits(exit);
00687 if((loc != Location(player)) && (loc != player) && !Wizard(player)) {
00688 notify_quiet(player, "You can not destroy exits in another room.");
00689 return 0;
00690 }
00691 return 1;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700 static int destroyable(dbref victim)
00701 {
00702 if((victim == mudconf.default_home) || (victim == mudconf.start_home)
00703 || (victim == mudconf.start_room) ||
00704 (victim == mudconf.master_room) || (victim == (dbref) 0) ||
00705 (God(victim)))
00706 return 0;
00707 return 1;
00708 }
00709
00710 static int can_destroy_player(dbref player, dbref victim)
00711 {
00712 if(!Wizard(player)) {
00713 notify_quiet(player, "Sorry, no suicide allowed.");
00714 return 0;
00715 }
00716 if(Wizard(victim)) {
00717 notify_quiet(player, "You may not destroy Wizards!");
00718 return 0;
00719 }
00720 return 1;
00721 }
00722
00723 void do_destroy(dbref player, dbref cause, int key, char *what)
00724 {
00725 dbref thing;
00726
00727
00728
00729
00730
00731 thing = match_controlled_quiet(player, what);
00732
00733
00734
00735
00736
00737 if((thing == NOTHING) && controls(player, Location(player))) {
00738 init_match(player, what, TYPE_EXIT);
00739 match_exit();
00740 thing = last_match_result();
00741 }
00742
00743
00744
00745
00746 if(thing == NOTHING) {
00747 init_match(player, what, TYPE_THING);
00748 match_possession();
00749 thing = last_match_result();
00750 if((thing != NOTHING) && !(isThing(thing) && Destroy_ok(thing))) {
00751 thing = NOPERM;
00752 }
00753 }
00754
00755
00756
00757
00758 if(match_status(player, thing) == NOTHING) {
00759 return;
00760 }
00761
00762
00763
00764
00765 if(Safe(thing, player) && !(key & DEST_OVERRIDE) && !(isThing(thing)
00766 &&
00767 Destroy_ok(thing)))
00768 {
00769 notify_quiet(player,
00770 "Sorry, that object is protected. Use @destroy/override to destroy it.");
00771 return;
00772 }
00773
00774
00775
00776
00777 if(!destroyable(thing)) {
00778 notify_quiet(player, "You can't destroy that!");
00779 return;
00780 }
00781
00782
00783
00784
00785 switch (Typeof(thing)) {
00786 case TYPE_EXIT:
00787 if(can_destroy_exit(player, thing)) {
00788 if(Going(thing)) {
00789 notify_quiet(player, "No sense beating a dead exit.");
00790 } else {
00791 if(Hardcode(thing)) {
00792 DisposeSpecialObject(player, thing);
00793 c_Hardcode(thing);
00794 }
00795 if(Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
00796 destroy_exit(thing);
00797 } else {
00798 notify(player, "The exit shakes and begins to crumble.");
00799 if(!Quiet(thing) && !Quiet(Owner(thing)))
00800 notify_quiet(Owner(thing),
00801 tprintf
00802 ("You will be rewarded shortly for %s(#%d).",
00803 Name(thing), thing));
00804 if((Owner(thing) != player) && !Quiet(player))
00805 notify_quiet(player,
00806 tprintf("Destroyed. #%d's %s(#%d)",
00807 Owner(thing), Name(thing),
00808 thing));
00809 s_Going(thing);
00810
00811 }
00812 }
00813 }
00814 break;
00815 case TYPE_THING:
00816 if(Going(thing)) {
00817 notify_quiet(player, "No sense beating a dead object.");
00818 } else {
00819 if(Hardcode(thing)) {
00820 DisposeSpecialObject(player, thing);
00821 c_Hardcode(thing);
00822 }
00823 if(Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
00824 destroy_thing(thing);
00825 } else {
00826 notify(player, "The object shakes and begins to crumble.");
00827 if(!Quiet(thing) && !Quiet(Owner(thing)))
00828 notify_quiet(Owner(thing),
00829 tprintf
00830 ("You will be rewarded shortly for %s(#%d).",
00831 Name(thing), thing));
00832 if((Owner(thing) != player) && !Quiet(player))
00833 notify_quiet(player, tprintf("Destroyed. %s's %s(#%d)",
00834 Name(Owner(thing)),
00835 Name(thing), thing));
00836 s_Going(thing);
00837 }
00838 }
00839 break;
00840 case TYPE_PLAYER:
00841 if(can_destroy_player(player, thing)) {
00842 if(Going(thing)) {
00843 notify_quiet(player, "No sense beating a dead player.");
00844 } else {
00845 if(Hardcode(thing)) {
00846 DisposeSpecialObject(player, thing);
00847 c_Hardcode(thing);
00848 }
00849 if(Destroy_ok(thing)) {
00850 atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
00851 destroy_player(thing);
00852 } else {
00853 notify(player,
00854 "The player shakes and begins to crumble.");
00855 s_Going(thing);
00856 atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
00857 }
00858 }
00859 }
00860 break;
00861 case TYPE_ROOM:
00862 if(Going(thing)) {
00863 notify_quiet(player, "No sense beating a dead room.");
00864 } else {
00865 if(Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
00866 empty_obj(thing);
00867 destroy_obj(NOTHING, thing);
00868 } else {
00869 notify_all(thing, player,
00870 "The room shakes and begins to crumble.");
00871 if(!Quiet(thing) && !Quiet(Owner(thing)))
00872 notify_quiet(Owner(thing),
00873 tprintf
00874 ("You will be rewarded shortly for %s(#%d).",
00875 Name(thing), thing));
00876 if((Owner(thing) != player) && !Quiet(player))
00877 notify_quiet(player, tprintf("Destroyed. %s's %s(#%d)",
00878 Name(Owner(thing)),
00879 Name(thing), thing));
00880 s_Going(thing);
00881 }
00882 }
00883 }
00884 }