/** Open a new exit. * \verbatim * This is the top-level function for @open. It calls do_real_open() * to do the real work of opening both the exit forward and the exit back. * \endverbatim * \param player the enactor. * \param direction name of the exit forward. * \param links 1-based array, possibly containing name of destination, name of exit back, * and room to open initial exit from. */ void do_open(dbref player, const char *direction, char **links) { dbref forward; dbref source = NOTHING; if (links[3]) { source = match_result(player, links[3], TYPE_ROOM, MAT_HERE | MAT_ABSOLUTE | MAT_TYPE); if (!GoodObject(source)) { notify(player, T("Open from where?")); return; } } forward = do_real_open(player, direction, links[1], source); if (links[2] && GoodObject(forward) && GoodObject(Location(forward))) { char sourcestr[SBUF_LEN]; /* SBUF_LEN is the size used by unparse_dbref */ if (!GoodObject(source)) { if (IsRoom(player)) { source = player; } else if (IsExit(player)) { source = Home(player); } else { source = Location(player); } } strcpy(sourcestr, unparse_dbref(source)); do_real_open(player, links[2], sourcestr, Location(forward)); } }
/** Open a new exit. * \verbatim * This is the top-level function for @open. It calls do_real_open() * to do the real work of opening both the exit forward and the exit back. * \endverbatim * \param player the enactor. * \param direction name of the exit forward. * \param links 1-based array, possibly containing name of destination, name of exit back, * and room to open initial exit from. * \param pe_info the pe_info to use for any lock checks */ void do_open(dbref player, const char *direction, char **links, NEW_PE_INFO *pe_info) { dbref forward; dbref source = NOTHING; if (links[3]) { source = match_result(player, links[3], TYPE_ROOM, MAT_HERE | MAT_ABSOLUTE | MAT_TYPE); if (!GoodObject(source)) { notify(player, T("Open from where?")); return; } } if (links[5]) { if (!make_first_free_wrapper(player, links[5])) return; } if (links[4]) { if (!make_first_free_wrapper(player, links[4])) return; } forward = do_real_open(player, direction, links[1], source, pe_info); if (links[2] && *links[2] && GoodObject(forward) && GoodObject(Location(forward))) { char sourcestr[SBUF_LEN]; /* SBUF_LEN is the size used by unparse_dbref */ if (!GoodObject(source)) { source = speech_loc(player); } strcpy(sourcestr, unparse_dbref(source)); do_real_open(player, links[2], sourcestr, Location(forward), pe_info); } }
/** Clone an object. * \verbatim * This is the top-level function for @clone, which creates a duplicate * of a (non-player) object. * \endverbatim * \param player the enactor. * \param name the name of the object to clone. * \param newname the name to give the duplicate. * \param preserve if 1, preserve ownership and privileges on duplicate. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of the duplicate, or NOTHING. */ dbref do_clone(dbref player, char *name, char *newname, int preserve, char *newdbref) { dbref clone, thing; char dbnum[BUFFER_LEN]; thing = noisy_match_result(player, name, NOTYPE, MAT_EVERYTHING); if ((thing == NOTHING)) return NOTHING; if (newname && *newname && !ok_name(newname, IsExit(thing))) { notify(player, T("That is not a reasonable name.")); return NOTHING; } if (!controls(player, thing) || IsPlayer(thing) || (IsRoom(thing) && !command_check_byname(player, "@dig")) || (IsExit(thing) && !command_check_byname(player, "@open")) || (IsThing(thing) && !command_check_byname(player, "@create"))) { notify(player, T("Permission denied.")); return NOTHING; } /* don't allow cloning of destructed things */ if (IsGarbage(thing)) { notify(player, T("There's nothing left of it to clone!")); return NOTHING; } if (preserve && !Wizard(player)) { notify(player, T("You cannot @CLONE/PRESERVE. Use normal @CLONE instead.")); return NOTHING; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } /* make sure owner can afford it */ switch (Typeof(thing)) { case TYPE_THING: if (can_pay_fees(player, Pennies(thing))) { clone = clone_object(player, thing, newname, preserve); notify_format(player, T("Cloned: Object %s."), unparse_dbref(clone)); if (IsRoom(player)) moveto(clone, player, player, "cloned"); else moveto(clone, Location(player), player, "cloned"); current_state.things++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_ROOM: if (can_pay_fees(player, ROOM_COST)) { clone = clone_object(player, thing, newname, preserve); Exits(clone) = NOTHING; notify_format(player, T("Cloned: Room #%d."), clone); current_state.rooms++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_EXIT: /* For exits, we don't want people to be able to link it to a location they can't with @open. So, all this stuff. */ switch (Location(thing)) { case NOTHING: strcpy(dbnum, "#-1"); break; case HOME: strcpy(dbnum, "home"); break; case AMBIGUOUS: strcpy(dbnum, "variable"); break; default: strcpy(dbnum, unparse_dbref(Location(thing))); } if (newname && *newname) clone = do_real_open(player, newname, dbnum, NOTHING); else clone = do_real_open(player, Name(thing), dbnum, NOTHING); if (!GoodObject(clone)) { return NOTHING; } else { atr_cpy(clone, thing); clone_locks(player, thing, clone); Zone(clone) = Zone(thing); Parent(clone) = Parent(thing); Flags(clone) = clone_flag_bitmask("FLAG", Flags(thing)); if (!preserve) { clear_flag_internal(clone, "WIZARD"); clear_flag_internal(clone, "ROYALTY"); Warnings(clone) = 0; /* zap warnings */ Powers(clone) = new_flag_bitmask("POWER"); /* zap powers */ } else { Warnings(clone) = Warnings(thing); Powers(clone) = clone_flag_bitmask("POWER", Powers(thing)); } if (Wizard(clone) || Royalty(clone) || Warnings(clone) || !null_flagmask("POWER", Powers(clone))) notify(player, T ("Warning: @CLONE/PRESERVE on an object with WIZ, ROY, @powers, or @warnings.")); notify_format(player, T("Cloned: Exit #%d."), clone); local_data_clone(clone, thing); return clone; } } return NOTHING; }
/** Create a room. * \verbatim * This is the top-level interface for @dig. * \endverbatim * \param player the enactor. * \param name the name of the room to create. * \param argv array of additional arguments to command * (exit forward,exit back,newdbref) * \param tport if 1, teleport the player to the new room. * \return dbref of new room, or NOTHING. */ dbref do_dig(dbref player, const char *name, char **argv, int tport) { dbref room; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; char *newdbref = NULL; if (argv[3] && *argv[3]) { newdbref = argv[3]; } /* we don't need to know player's location! hooray! */ if (*name == '\0') { notify(player, T("Dig what?")); } else if (!ok_name(name, 0)) { notify(player, T("That's a silly name for a room!")); } else if (can_pay_fees(player, ROOM_COST)) { if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } room = new_object(); /* Initialize everything */ set_name(room, name); Owner(room) = Owner(player); Zone(room) = Zone(player); Type(room) = TYPE_ROOM; Flags(room) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.room_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", room, flagname, 0); } } notify_format(player, T("%s created with room number %d."), name, room); if (argv[1] && *argv[1]) { char nbuff[MAX_COMMAND_LEN]; sprintf(nbuff, "#%d", room); do_real_open(player, argv[1], nbuff, NOTHING); } if (argv[2] && *argv[2]) { do_real_open(player, argv[2], "here", room); } current_state.rooms++; local_data_create(room); if (tport) { /* We need to use the full command, because we need NO_TEL * and Z_TEL checking */ char roomstr[MAX_COMMAND_LEN]; sprintf(roomstr, "#%d", room); do_teleport(player, "me", roomstr, 0, 0); /* if flag, move the player */ } queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(room)); return room; } return NOTHING; }