/** A wrapper for real_did_it that clears the environment first. * \param player the enactor. * \param thing object being triggered. * \param what message attribute for enactor. * \param def default message to enactor. * \param owhat message attribute for others. * \param odef default message to others. * \param awhat action attribute to trigger. * \param loc location in which action is taking place. * \retval 0 no attributes were evaluated (only defaults used). * \retval 1 some attributes were evaluated. */ int did_it(dbref player, dbref thing, const char *what, const char *def, const char *owhat, const char *odef, const char *awhat, dbref loc, int an_flags) { return real_did_it(player, thing, what, def, owhat, odef, awhat, loc, NULL, NA_INTER_HEAR, an_flags); }
/** A wrapper for did_it that can pass interaction flags. * \param player the enactor. * \param thing object being triggered. * \param what message attribute for enactor. * \param def default message to enactor. * \param owhat message attribute for others. * \param odef default message to others. * \param awhat action attribute to trigger. * \param loc location in which action is taking place. * \param flags interaction flags to pass to real_did_it. * \retval 0 no attributes were present, only defaults were used if given. * \retval 1 some attributes were evaluated and used. */ int did_it_interact(dbref player, dbref thing, const char *what, const char *def, const char *owhat, const char *odef, const char *awhat, dbref loc, int flags, int an_flags) { /* Bunch o' nulls */ return real_did_it(player, thing, what, def, owhat, odef, awhat, loc, NULL, flags, an_flags); }
/** A wrapper for real_did_it that can set %0 and %1 to dbrefs. * \param player the enactor. * \param thing object being triggered. * \param what message attribute for enactor. * \param def default message to enactor. * \param owhat message attribute for others. * \param odef default message to others. * \param awhat action attribute to trigger. * \param loc location in which action is taking place. * \param env0 dbref to pass as %0, or NOTHING. * \param env1 dbref to pass as %1, or NOTHING. * \param flags interaction flags to pass to real_did_it. * \retval 0 no attributes were present, only defaults were used if given. * \retval 1 some attributes were evaluated and used. */ int did_it_with(dbref player, dbref thing, const char *what, const char *def, const char *owhat, const char *odef, const char *awhat, dbref loc, dbref env0, dbref env1, int flags, int an_flags) { PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "did_it_with"); int retval; if (env0 != NOTHING) { pe_regs_setenv(pe_regs, 0, unparse_dbref(env0)); } if (env1 != NOTHING) { pe_regs_setenv(pe_regs, 1, unparse_dbref(env1)); } retval = real_did_it(player, thing, what, def, owhat, odef, awhat, loc, pe_regs, flags, an_flags); pe_regs_free(pe_regs); return retval; }
/** 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; }
/** Rename something. * \verbatim * This implements @name. * \endverbatim * \param player the enactor. * \param name current name of object to rename. * \param newname_ new name for object. */ void do_name(dbref player, const char *name, char *newname_) { dbref thing; char oldname[BUFFER_LEN]; char *newname = NULL; char *alias = NULL; PE_REGS *pe_regs; if ((thing = match_controlled(player, name)) == NOTHING) return; /* check for bad name */ if ((*newname_ == '\0') || strchr(newname_, '[')) { notify(player, T("Give it what new name?")); return; } switch (Typeof(thing)) { case TYPE_PLAYER: switch (ok_object_name (newname_, player, thing, TYPE_PLAYER, &newname, &alias)) { case OPAE_INVALID: case OPAE_NULL: notify(player, T("You can't give a player that name or alias.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; case OPAE_TOOMANY: notify(player, T("Too many aliases.")); mush_free(newname, "name.newname"); return; case OPAE_SUCCESS: break; } break; case TYPE_EXIT: if (ok_object_name(newname_, player, thing, TYPE_EXIT, &newname, &alias) != OPAE_SUCCESS) { notify(player, T("That is not a reasonable name.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; } break; case TYPE_THING: case TYPE_ROOM: if (!ok_name(newname_, 0)) { notify(player, T("That is not a reasonable name.")); return; } newname = mush_strdup(trim_space_sep(newname_, ' '), "name.newname"); break; default: /* Should never occur */ notify(player, T("I don't see that here.")); return; } /* Actually change it */ mush_strncpy(oldname, Name(thing), BUFFER_LEN); if (IsPlayer(thing)) { do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s", Name(thing), thing, newname); if (Suspect(thing) && strcmp(Name(thing), newname) != 0) flag_broadcast("WIZARD", 0, T("Broadcast: Suspect %s changed name to %s."), Name(thing), newname); reset_player_list(thing, Name(thing), NULL, newname, NULL); } set_name(thing, newname); if (alias) { if (*alias == ALIAS_DELIMITER) { do_set_atr(thing, "ALIAS", NULL, player, 0); } else { /* New alias to set */ do_set_atr(thing, "ALIAS", alias, player, 0); } mush_free(alias, "name.newname"); } queue_event(player, "OBJECT`RENAME", "%s,%s,%s", unparse_objid(thing), newname, oldname); if (!AreQuiet(player, thing)) notify(player, T("Name set.")); pe_regs = pe_regs_create(PE_REGS_ARG, "do_name"); pe_regs_setenv_nocopy(pe_regs, 0, oldname); pe_regs_setenv_nocopy(pe_regs, 1, newname); real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING, pe_regs, NA_INTER_PRESENCE, AN_SYS); pe_regs_free(pe_regs); mush_free(newname, "name.newname"); }
/** User-defined verbs. * \verbatim * This implements the @verb command. * \endverbatim * \param executor the executor. * \param enactor the object causing this command to run. * \param arg1 the object to read verb attributes from. * \param argv the array of remaining arguments to the verb command. * \param queue_entry The queue entry \@verb is running in */ void do_verb(dbref executor, dbref enactor, char *arg1, char **argv, MQUE *queue_entry) { dbref victim; dbref actor; int i; PE_REGS *pe_regs = NULL; /* find the object that we want to read the attributes off * (the object that was the victim of the command) */ /* our victim object can be anything */ victim = match_result(executor, arg1, NOTYPE, MAT_EVERYTHING); if (!GoodObject(victim)) { notify(executor, T("What was the victim of the verb?")); return; } /* find the object that executes the action */ if (!argv || !argv[1] || !*argv[1]) { notify(executor, T("What do you want to do with the verb?")); return; } actor = match_result(executor, argv[1], NOTYPE, MAT_EVERYTHING); if (!GoodObject(actor)) { notify(executor, T("What do you want to do the verb?")); return; } /* Control check is fascist. * First check: we don't want <actor> to do something involuntarily. * Both victim and actor have to be controlled by the thing which did * the @verb (for speed we do a WIZARD check first), or: cause controls * actor plus the second check is passed. * Second check: we need read access to the attributes. * Either the player controls victim or the player * must be priviledged, or the victim has to be VISUAL. */ if (!(Wizard(executor) || (controls(executor, victim) && controls(executor, actor)) || ((controls(enactor, actor) && Can_Examine(executor, victim))))) { notify(executor, T("Permission denied.")); return; } /* We're okay. Send out messages. */ pe_regs = pe_regs_create(PE_REGS_ARG | PE_REGS_Q, "do_verb"); for (i = 0; i < MAX_STACK_ARGS; i++) { if (argv[i + 7]) { pe_regs_setenv_nocopy(pe_regs, i, argv[i + 7]); } } pe_regs_qcopy(pe_regs, queue_entry->pe_info->regvals); real_did_it(actor, victim, upcasestr(argv[2]), argv[3], upcasestr(argv[4]), argv[5], NULL, Location(actor), pe_regs, NA_INTER_HEAR, AN_SYS); /* Now we copy our args into the stack, and do the command. */ if (argv[6] && *argv[6]) queue_attribute_base(victim, upcasestr(argv[6]), actor, 0, pe_regs, (queue_entry->queue_type & QUEUE_EVENT)); pe_regs_free(pe_regs); }