/** Can player pemit to target? * You can pemit if you're pemit_all, if you're pemitting to yourself, * if you're pemitting to a non-player, or if you pass target's * pagelock and target isn't HAVEN. * \param player dbref attempting to pemit. * \param target target dbref to pemit to. * \param dofails If nonzero, send failure message 'def' or run fail_lock() * \param def show a default message if there is no appropriate failure message? * \param pe_info the pe_info for page lock evaluation * \retval 1 player may pemit to target. * \retval 0 player may not pemit to target. */ int okay_pemit(dbref player, dbref target, int dofails, int def, NEW_PE_INFO *pe_info) { char defmsg[BUFFER_LEN]; char *dp = NULL; if (Pemit_All(player)) return 1; if (dofails && def) { dp = defmsg; safe_format(defmsg, &dp, T("I'm sorry, but %s wishes to be left alone now."), AName(target, AN_SYS, NULL)); *dp = '\0'; dp = defmsg; } if (IsPlayer(target) && Haven(target)) { if (dofails && def) notify(player, dp); return 0; } if (!eval_lock_with(player, target, Page_Lock, pe_info)) { if (dofails) { fail_lock(player, target, Page_Lock, dp, NOTHING); } return 0; } return 1; }
/** 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); }
/** Change an object's zone. * \verbatim * This implements @chzone. * \endverbatim * \param player the enactor. * \param name name of the object to change zone of. * \param newobj name of new ZMO. * \param noisy if 1, notify player about success and failure. * \param preserve was the /preserve switch given? * \param pe_info the pe_info for lock and permission checks * \retval 0 failed to change zone. * \retval 1 successfully changed zone. */ int do_chzone(dbref player, char const *name, char const *newobj, bool noisy, bool preserve, NEW_PE_INFO *pe_info) { dbref thing; dbref zone; int has_lock; if ((thing = noisy_match_result(player, name, NOTYPE, MAT_NEARBY)) == NOTHING) return 0; if (!newobj || !*newobj || !strcasecmp(newobj, "none")) zone = NOTHING; else { if ((zone = noisy_match_result(player, newobj, NOTYPE, MAT_EVERYTHING)) == NOTHING) return 0; } if (Zone(thing) == zone) { if (noisy) notify(player, T("That object is already in that zone.")); return 0; } if (!controls(player, thing)) { if (noisy) notify(player, T("You don't have the power to shift reality.")); return 0; } /* a player may change an object's zone to: * 1. NOTHING * 2. an object he controls * 3. an object with a chzone-lock that the player passes. * Note that an object with no chzone-lock isn't valid */ has_lock = (getlock(zone, Chzone_Lock) != TRUE_BOOLEXP); if (!(Wizard(player) || (zone == NOTHING) || controls(player, zone) || (has_lock && eval_lock_with(player, zone, Chzone_Lock, pe_info)))) { if (noisy) { if (has_lock) { fail_lock(player, zone, Chzone_Lock, T("You cannot move that object to that zone."), NOTHING); } else { notify(player, T("You cannot move that object to that zone.")); } } return 0; } /* Don't chzone object to itself for mortals! */ if ((zone == thing) && !Hasprivs(player)) { if (noisy) notify(player, T("You shouldn't zone objects to themselves!")); return 0; } /* Don't allow circular zones */ if (GoodObject(zone)) { dbref tmp; int zone_depth = MAX_ZONES; for (tmp = Zone(zone); GoodObject(tmp); tmp = Zone(tmp)) { if (tmp == thing) { notify(player, T("You can't make circular zones!")); return 0; } if (tmp == Zone(tmp)) /* Ran into an object zoned to itself */ break; zone_depth--; if (!zone_depth) { notify(player, T("Overly deep zone chain.")); return 0; } } } /* Don't allow chzone to objects without elocks! * If no lock is set, set a default lock (warn if zmo are used for control) * This checks for many trivial elocks (canuse/1, where &canuse=1) */ if (zone != NOTHING) check_zone_lock(player, zone, noisy); /* Warn Wiz/Royals when they zone their stuff */ if ((zone != NOTHING) && Hasprivs(Owner(thing))) { if (noisy) notify(player, T("Warning: @chzoning admin-owned object!")); } /* everything is okay, do the change */ Zone(thing) = zone; /* If we're not unzoning, and we're working with a non-player object, * we'll remove wizard, royalty, inherit, and powers, for security, unless * a wizard is changing the zone and explicitly says not to. */ if (!Wizard(player)) preserve = 0; if (!preserve && ((zone != NOTHING) && !IsPlayer(thing))) { /* if the object is a player, resetting these flags is rather * inconvenient -- although this may pose a bit of a security * risk. Be careful when @chzone'ing wizard or royal players. */ clear_flag_internal(thing, "WIZARD"); clear_flag_internal(thing, "ROYALTY"); clear_flag_internal(thing, "TRUST"); destroy_flag_bitmask("POWER", Powers(thing)); Powers(thing) = new_flag_bitmask("POWER"); } else { if (noisy && (zone != NOTHING)) { if (Hasprivs(thing)) notify(player, T("Warning: @chzoning a privileged player.")); if (Inherit(thing)) notify(player, T("Warning: @chzoning a TRUST player.")); } } if (noisy) notify(player, T("Zone changed.")); return 1; }
/** The oemit(/list) command. * \verbatim * This implements @oemit and @oemit/list. * \endverbatim * \param executor The object \@oemit'ing * \param speaker The object making the sound (executor, unless /spoof'ing) * \param list the list of dbrefs to oemit from the emit. * \param message the message to emit. * \param flags PEMIT_* flags. * \param format a format_msg structure to pass to notify_anything() from \@message * \param pe_info the pe_info to use for evaluating speech locks */ void do_oemit_list(dbref executor, dbref speaker, char *list, const char *message, int flags, struct format_msg *format, NEW_PE_INFO *pe_info) { char *temp, *p; const char *s; dbref who; dbref room; int matched = 0; dbref pass[11]; dbref locs[10]; int i, oneloc = 0; int na_flags = NA_INTER_HEAR | NA_PROPAGATE; /* If no message, further processing is pointless. * If no list, they should have used @remit. */ if (!message || !*message || !list || !*list) return; if (flags & PEMIT_SPOOF) na_flags |= NA_SPOOF; for (i = 0; i < 11; i++) pass[i] = NOTHING; /* Find out what room to do this in. If they supplied a db# before * the '/', then oemit to anyone in the room who's not on list. * Otherwise, oemit to every location which has at least one of the * people in the list. This is intended for actions which involve * players who are in different rooms, e.g.: * * X (in #0) fires an arrow at Y (in #2). * * X sees: You fire an arrow at Y. (pemit to X) * Y sees: X fires an arrow at you! (pemit to Y) * #0 sees: X fires an arrow at Y. (oemit/list to X Y) * #2 sees: X fires an arrow at Y. (from the same oemit) */ /* Find out what room to do this in. They should have supplied a db# * before the '/'. */ if ((temp = strchr(list, '/'))) { *temp++ = '\0'; room = noisy_match_result(executor, list, NOTYPE, MAT_EVERYTHING); if (!GoodObject(room)) { notify(executor, T("I can't find that room.")); return; } if (!Loud(speaker) && !eval_lock_with(speaker, room, Speech_Lock, pe_info)) { fail_lock(executor, room, Speech_Lock, T("You may not speak there!"), NOTHING); return; } oneloc = 1; /* we are only oemitting to one location */ } else { temp = list; } s = temp; while (s && *s) { p = next_in_list(&s); /* If a room was given, we match relative to the room */ if (oneloc) who = match_result_relative(executor, room, p, NOTYPE, MAT_OBJ_CONTENTS); else who = noisy_match_result(executor, p, NOTYPE, MAT_OBJECTS); /* matched tracks the number of valid players we've found. * room is the given room (possibly nothing right now) * pass[0..10] are dbrefs of players * locs[0..10] are corresponding dbrefs of locations * pass[11] is always NOTHING */ if (GoodObject(who) && GoodObject(Location(who)) && (Loud(speaker) || (oneloc && Location(who) == room) || eval_lock_with(speaker, Location(who), Speech_Lock, pe_info)) ) { if (matched < 10) { locs[matched] = Location(who); pass[matched] = who; matched++; } else { notify(executor, T("Too many people to oemit to.")); break; } } } if (!matched) { if (oneloc) { /* A specific location was given, but there were no matching objects to * omit, so just remit */ notify_anything(executor, speaker, na_loc, &room, NULL, na_flags, message, NULL, room, format); } else { notify(executor, T("No matching objects.")); } return; } /* Sort the list of rooms to oemit to so we don't oemit to the same * room twice */ qsort((void *) locs, matched, sizeof(locs[0]), dbref_comp); for (i = 0; i < matched; i++) { if (i != 0 && locs[i] == locs[i - 1]) continue; notify_anything(executor, speaker, na_loc, &locs[i], pass, na_flags, message, NULL, locs[i], format); } }