예제 #1
0
파일: speech.c 프로젝트: kymoon/pennmush
/** 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;
}
예제 #2
0
파일: speech.c 프로젝트: kymoon/pennmush
/** 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);
}
예제 #3
0
파일: speech.c 프로젝트: kymoon/pennmush
/** 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);
}
예제 #4
0
/** 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;
}
예제 #5
0
파일: speech.c 프로젝트: kymoon/pennmush
/** 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);
  }

}