void moveto(dbref what, dbref where) { dbref loc; /* do NOT move garbage */ if (what != NOTHING && Typeof(what) == TYPE_GARBAGE) { return; } if(what != NOTHING && parent_loop_check(what, where)) { /* Prevent stupid loop holes elsewhere */ return; } /* remove what from old loc */ if ((loc = DBFETCH(what)->location) != NOTHING) { DBSTORE(loc, contents, remove_first(DBFETCH(loc)->contents, what)); } /* test for special cases */ switch (where) { case NOTHING: DBSTORE(what, location, NOTHING); return; /* NOTHING doesn't have contents */ case HOME: switch (Typeof(what)) { case TYPE_PLAYER: where = DBFETCH(what)->sp.player.home; break; case TYPE_THING: where = DBFETCH(what)->sp.thing.home; if (parent_loop_check(what, where)) where = DBFETCH(OWNER(what))->sp.player.home; break; case TYPE_ROOM: where = GLOBAL_ENVIRONMENT; break; case TYPE_PROGRAM: where = OWNER(what); break; } } /* now put what in where */ PUSH(what, DBFETCH(where)->contents); DBDIRTY(where); DBSTORE(what, location, where); }
/* do_link * * Use this to link to a room that you own. It also sets home for * objects and things, and drop-to's for rooms. * It seizes ownership of an unlinked exit, and costs 1 penny * plus a penny transferred to the exit owner if they aren't you * * All destinations must either be owned by you, or be LINK_OK. */ void do_link(int descr, dbref player, const char *thing_name, const char *dest_name) { dbref good_dest[MAX_LINKS]; int ndest, i; struct match_data md; char buf[BUFFER_LEN]; dbref thing, dest; if (tp_db_readonly) { anotify_nolisten2(player, CFAIL DBRO_MESG); return; } if (Guest(player)) { anotify_fmt(player, CFAIL "%s", tp_noguest_mesg); return; } init_match(descr, player, thing_name, TYPE_EXIT, &md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); if (Mage(OWNER(player))) match_player(&md); if ((thing = noisy_match_result(&md)) == NOTHING) return; switch (Typeof(thing)) { case TYPE_EXIT: /* we're ok, check the usual stuff */ if (DBFETCH(thing)->sp.exit.ndest != 0) { if (controls(player, thing)) { if ((DBFETCH(thing)->sp.exit.dest)[0] != NIL) { anotify_nolisten2(player, CINFO "That exit is already linked."); return; } } else { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } } /* handle costs */ if (OWNER(thing) == OWNER(player)) { if (!payfor(player, tp_link_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", tp_link_cost, (tp_link_cost == 1) ? tp_penny : tp_pennies); return; } } else { if (!payfor(player, tp_link_cost + tp_exit_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", (tp_link_cost + tp_exit_cost), (tp_link_cost + tp_exit_cost == 1) ? tp_penny : tp_pennies); return; } else if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } else { /* pay the owner for his loss */ dbref owner = OWNER(thing); DBFETCH(owner)->sp.player.pennies += tp_exit_cost; DBDIRTY(owner); } } /* link has been validated and paid for; do it */ OWNER(thing) = OWNER(player); if (! (ndest = link_exit(descr, player, thing, (char *) dest_name, good_dest))) { anotify_nolisten2(player, CFAIL "No destinations linked."); DBFETCH(player)->sp.player.pennies += tp_link_cost; /* Refund! */ DBDIRTY(player); break; } DBFETCH(thing)->sp.exit.ndest = ndest; if (DBFETCH(thing)->sp.exit.dest) free(DBFETCH(thing)->sp.exit.dest); DBFETCH(thing)->sp.exit.dest = (dbref *) malloc(sizeof(dbref) * ndest); for (i = 0; i < ndest; i++) (DBFETCH(thing)->sp.exit.dest)[i] = good_dest[i]; break; case TYPE_THING: case TYPE_PLAYER: init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_absolute(&md); match_registered(&md); match_me(&md); match_here(&md); match_null(&md); if (Typeof(thing) == TYPE_THING) match_possession(&md); if ((dest = noisy_match_result(&md)) == NOTHING) return; if (Typeof(thing) == TYPE_THING && dest == NIL) { anotify_fmt(player, CFAIL "%s", "You cannot HOME a THING to NIL."); return; } if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } if (parent_loop_check(thing, dest)) { anotify_nolisten2(player, CFAIL "That would cause a parent paradox."); return; } /* do the link */ if (Typeof(thing) == TYPE_THING) { DBFETCH(thing)->sp.thing.home = dest; } else DBFETCH(thing)->sp.player.home = dest; sprintf(buf, CSUCC "%s's home set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); break; case TYPE_ROOM: /* room dropto's */ init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_possession(&md); match_registered(&md); match_absolute(&md); match_home(&md); match_null(&md); if ((dest = noisy_match_result(&md)) == NOTHING) break; if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest) || (thing == dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); } else { DBFETCH(thing)->sp.room.dropto = dest; /* dropto */ sprintf(buf, CSUCC "%s's dropto set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); } break; case TYPE_PROGRAM: anotify_nolisten2(player, CFAIL "You can't link programs to things!"); break; default: anotify_nolisten2(player, CFAIL "Weird object type."); log_status("*BUG: weird object: Typeof(%d) = %d\n", thing, Typeof(thing)); break; } DBDIRTY(thing); return; }
void do_teleport(int descr, dbref player, const char *arg1, const char *arg2) { dbref victim; dbref destination; const char *to; struct match_data md; /* get victim, destination */ if (*arg2 == '\0') { victim = player; to = arg1; } else { init_match(descr, player, arg1, NOTYPE, &md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); match_player(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { return; } to = arg2; } #ifdef GOD_PRIV if(tp_strict_god_priv && !God(player) && God(OWNER(victim))) { notify(player, "God has already set that where He wants it to be."); return; } #endif /* get destination */ init_match(descr, player, to, TYPE_PLAYER, &md); match_possession(&md); match_me(&md); match_here(&md); match_home(&md); match_absolute(&md); match_registered(&md); if (Wizard(OWNER(player))) { match_neighbor(&md); match_player(&md); } switch (destination = match_result(&md)) { case NOTHING: notify(player, "Send it where?"); break; case AMBIGUOUS: notify(player, "I don't know which destination you mean!"); break; case HOME: switch (Typeof(victim)) { case TYPE_PLAYER: destination = PLAYER_HOME(victim); if (parent_loop_check(victim, destination)) destination = PLAYER_HOME(OWNER(victim)); break; case TYPE_THING: destination = THING_HOME(victim); if (parent_loop_check(victim, destination)) { destination = PLAYER_HOME(OWNER(victim)); if (parent_loop_check(victim, destination)) { destination = (dbref) 0; } } break; case TYPE_ROOM: destination = GLOBAL_ENVIRONMENT; break; case TYPE_PROGRAM: destination = OWNER(victim); break; default: destination = tp_player_start; /* caught in the next * switch anyway */ break; } default: switch (Typeof(victim)) { case TYPE_PLAYER: if (!controls(player, victim) || !controls(player, destination) || !controls(player, getloc(victim)) || (Typeof(destination) == TYPE_THING && !controls(player, getloc(destination)))) { notify(player, "Permission denied. (must control victim, dest, victim's loc, and dest's loc)"); break; } if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!Wizard(victim) && (Typeof(destination) == TYPE_THING && !(FLAGS(destination) & VEHICLE))) { notify(player, "Destination object is not a vehicle."); break; } if (parent_loop_check(victim, destination)) { notify(player, "Objects can't contain themselves."); break; } notify(victim, "You feel a wrenching sensation..."); enter_room(descr, victim, destination, DBFETCH(victim)->location); notify(player, "Teleported."); break; case TYPE_THING: if (parent_loop_check(victim, destination)) { notify(player, "You can't make a container contain itself!"); break; } case TYPE_PROGRAM: if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_PLAYER && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!((controls(player, destination) || can_link_to(player, NOTYPE, destination)) && (controls(player, victim) || controls(player, DBFETCH(victim)->location)))) { notify(player, "Permission denied. (must control dest and be able to link to it, or control dest's loc)"); break; } /* check for non-sticky dropto */ if (Typeof(destination) == TYPE_ROOM && DBFETCH(destination)->sp.room.dropto != NOTHING && !(FLAGS(destination) & STICKY)) destination = DBFETCH(destination)->sp.room.dropto; if (tp_thing_movement && (Typeof(victim) == TYPE_THING)) { enter_room(descr, victim, destination, DBFETCH(victim)->location); } else { moveto(victim, destination); } notify(player, "Teleported."); break; case TYPE_ROOM: if (Typeof(destination) != TYPE_ROOM) { notify(player, "Bad destination."); break; } if (!controls(player, victim) || !can_link_to(player, NOTYPE, destination) || victim == GLOBAL_ENVIRONMENT) { notify(player, "Permission denied. (Can't move #0, dest must be linkable, and must control victim)"); break; } if (parent_loop_check(victim, destination)) { notify(player, "Parent would create a loop."); break; } moveto(victim, destination); notify(player, "Parent set."); break; case TYPE_GARBAGE: notify(player, "That object is in a place where magic cannot reach it."); break; default: notify(player, "You can't teleport that."); break; } break; } return; }