/* utility for open and link */ static dbref parse_linkable_room(dbref player, const char *room_name, NEW_PE_INFO *pe_info) { dbref room; /* parse room */ if (!strcasecmp(room_name, "here")) { room = speech_loc(player); } else if (!strcasecmp(room_name, "home")) { return HOME; /* HOME is always linkable */ } else { room = parse_objid(room_name); } /* check room */ if (!GoodObject(room)) { notify(player, T("That is not a valid object.")); return NOTHING; } else if (Going(room)) { notify(player, T("That room is being destroyed. Sorry.")); return NOTHING; } else if (!can_link_to(player, room, pe_info)) { notify(player, T("You can't link to that.")); return NOTHING; } else { return room; } }
/** The teach command. * \param player the enactor. * \param tbuf1 the command being taught. * \param list is tbuf1 an action list, or a single command? * \param parent_queue the queue entry to run the command in */ void do_teach(dbref player, const char *tbuf1, int list, MQUE *parent_queue) { dbref loc; int flags = QUEUE_RECURSE; char lesson[BUFFER_LEN], *lp; loc = speech_loc(player); if (!GoodObject(loc)) return; if (!Loud(player) && !eval_lock_with(player, loc, Speech_Lock, parent_queue->pe_info)) { fail_lock(player, loc, Speech_Lock, T("You may not speak here!"), NOTHING); return; } if (!tbuf1 || !*tbuf1) { notify(player, T("What command do you want to teach?")); return; } if (!list) flags |= QUEUE_NOLIST; lp = lesson; safe_format(lesson, &lp, T("%s types --> %s%s%s"), spname(player), ANSI_HILITE, tbuf1, ANSI_END); *lp = '\0'; notify_anything(player, player, na_loc, &loc, NULL, NA_INTER_HEAR | NA_PROPAGATE, lesson, NULL, loc, NULL); new_queue_actionlist(player, parent_queue->enactor, player, (char *) tbuf1, parent_queue, PE_INFO_SHARE, flags, NULL); }
/** The say command. * \param player the enactor. * \param message the message to say. * \param pe_info pe_info to eval speechmod with */ void do_say(dbref player, const char *message, NEW_PE_INFO *pe_info) { dbref loc; PE_REGS *pe_regs; char modmsg[BUFFER_LEN]; char says[BUFFER_LEN]; char *sp; int mod = 0; loc = speech_loc(player); if (!GoodObject(loc)) return; if (!Loud(player) && !eval_lock_with(player, loc, Speech_Lock, pe_info)) { fail_lock(player, loc, Speech_Lock, T("You may not speak here!"), NOTHING); return; } if (*message == SAY_TOKEN && CHAT_STRIP_QUOTE) message++; pe_regs = pe_regs_create(PE_REGS_ARG, "do_say"); pe_regs_setenv_nocopy(pe_regs, 0, message); pe_regs_setenv_nocopy(pe_regs, 1, "\""); modmsg[0] = '\0'; if (call_attrib(player, "SPEECHMOD", modmsg, player, pe_info, pe_regs) && *modmsg != '\0') mod = 1; pe_regs_free(pe_regs); /* notify everybody */ notify_format(player, T("You say, \"%s\""), (mod ? modmsg : message)); sp = says; safe_format(says, &sp, T("%s says, \"%s\""), spname(player), (mod ? modmsg : message)); *sp = '\0'; notify_except(player, loc, player, says, NA_INTER_HEAR); }
/** 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); } }
/** Create an exit. * This function opens an exit and optionally links it. * \param player the enactor. * \param direction the name of the exit. * \param linkto the room to link to, as a string. * \param pseudo a phony location for player if a back exit is needed. This is bpass by do_open() as the source room of the back exit. * \param pe_info the pe_info to use for any lock checks * \return dbref of the new exit, or NOTHING. */ dbref do_real_open(dbref player, const char *direction, const char *linkto, dbref pseudo, NEW_PE_INFO *pe_info) { dbref loc = (pseudo != NOTHING) ? pseudo : speech_loc(player); dbref new_exit; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; char *name = NULL; char *alias = NULL; if (!command_check_byname(player, "@dig", NULL)) { notify(player, T("Permission denied.")); return NOTHING; } if ((loc == NOTHING) || (!IsRoom(loc))) { notify(player, T("Sorry, you can only make exits out of rooms.")); return NOTHING; } if (Going(loc)) { notify(player, T("You can't make an exit in a place that's crumbling.")); return NOTHING; } if (!*direction) { notify(player, T("Open where?")); return NOTHING; } else if (ok_object_name ((char *) direction, player, NOTHING, TYPE_EXIT, &name, &alias) != OPAE_SUCCESS) { notify(player, T("That's a strange name for an exit!")); if (name) mush_free(name, "name.newname"); if (alias) mush_free(alias, "name.newname"); return NOTHING; } if (!can_open_from(player, loc, pe_info)) { notify(player, T("Permission denied.")); } else if (can_pay_fees(player, EXIT_COST)) { /* create the exit */ new_exit = new_object(); /* initialize everything */ set_name(new_exit, name); Owner(new_exit) = Owner(player); Zone(new_exit) = Zone(player); Source(new_exit) = loc; Type(new_exit) = TYPE_EXIT; Flags(new_exit) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.exit_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", new_exit, flagname, 0); } } mush_free(name, "name.newname"); if (alias) { if (*alias != ALIAS_DELIMITER) atr_add(new_exit, "ALIAS", alias, player, 0); mush_free(alias, "name.newname"); } /* link it in */ PUSH(new_exit, Exits(loc)); /* and we're done */ notify_format(player, T("Opened exit %s"), unparse_dbref(new_exit)); /* check second arg to see if we should do a link */ if (linkto && *linkto != '\0') { notify(player, T("Trying to link...")); if ((loc = check_var_link(linkto)) == NOTHING) loc = parse_linkable_room(player, linkto, pe_info); if (loc != NOTHING) { if (!payfor(player, LINK_COST)) { notify_format(player, T("You don't have enough %s to link."), MONIES); } else { /* it's ok, link it */ Location(new_exit) = loc; notify_format(player, T("Linked exit #%d to #%d"), new_exit, loc); } } } current_state.exits++; local_data_create(new_exit); queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(new_exit)); return new_exit; } if (name) mush_free(name, "name.newname"); if (alias) mush_free(alias, "name.newname"); return NOTHING; }