コード例 #1
0
ファイル: set.c プロジェクト: captdeaf/pennmush
static int
chown_ok(dbref player, dbref thing, dbref newowner, NEW_PE_INFO *pe_info)
{
  /* Can't touch garbage */
  if (IsGarbage(thing))
    return 0;

  /* Wizards can do it all */
  if (Wizard(player))
    return 1;

  /* In order for non-wiz player to @chown thing to newowner,
   * player must control newowner or newowner must be a Zone Master
   * and player must pass its zone lock.
   *
   * In addition, one of the following must apply:
   *   1.  player owns thing, or
   *   2.  player controls Owner(thing), newowner is a zone master,
   *       and Owner(thing) passes newowner's zone-lock, or
   *   3.  thing is CHOWN_OK, and player holds thing if it's an object.
   *
   * The third condition is syntactic sugar to handle the situation
   * where Joe owns Box, an ordinary object, and Tool, an inherit object,
   * and ZMP, a Zone Master Player, is zone-locked to =tool.
   * In this case, if Joe doesn't pass ZMP's lock, we don't want
   *   Joe to be able to @fo Tool=@chown Box=ZMP
   */

  /* Does player control newowner, or is newowner a Zone Master and player
   * passes the lock?
   */
  if (!(controls(player, newowner) ||
        (ZMaster(newowner) &&
         eval_lock_with(player, newowner, Zone_Lock, pe_info))))
    return 0;

  /* Target player is legitimate. Does player control the object? */
  if (Owns(player, thing))
    return 1;

  if (controls(player, Owner(thing)) && ZMaster(newowner) &&
      eval_lock_with(Owner(thing), newowner, Zone_Lock, pe_info))
    return 1;

  if ((!IsThing(thing) || (Location(thing) == player)) && ChownOk(thing) &&
      eval_lock_with(player, thing, Chown_Lock, pe_info))
    return 1;

  return 0;
}
コード例 #2
0
/** lock evaluation -- determines if player passes lock on thing, for
 * the purposes of picking up an object or moving through an exit.
 * \param player to check against lock.
 * \param thing thing to check the basic lock on.
 * \param pe_info the pe_info for Basic lock evaluation
 * \retval 1 player passes lock.
 * \retval 0 player fails lock.
 */
int
could_doit(dbref player, dbref thing, NEW_PE_INFO *pe_info)
{
  if (!IsRoom(thing) && Location(thing) == NOTHING)
    return 0;
  return (eval_lock_with(player, thing, Basic_Lock, pe_info));
}
コード例 #3
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;
}
コード例 #4
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);
}
コード例 #5
0
ファイル: lock.c プロジェクト: MrWigggles/pennmush
/** Evaluate a lock, saving/clearing the env (%0-%9) and qreg (%q*) first,
 ** and restoring them after.
 */
int
eval_lock_clear(dbref player, dbref thing, lock_type ltype,
                NEW_PE_INFO *pe_info)
{
  if (!pe_info)
    return eval_lock_with(player, thing, ltype, NULL);
  else {
    PE_REGS *pe_regs;
    int result;

    pe_regs = pe_regs_localize(pe_info, PE_REGS_ISOLATE, "eval_lock_clear");

    /* Run the lock */
    result = eval_lock_with(player, thing, ltype, pe_info);

    /* Restore q-regs */
    pe_regs_restore(pe_info, pe_regs);
    pe_regs_free(pe_regs);
    return result;
  }
}
コード例 #6
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);
}
コード例 #7
0
ファイル: set.c プロジェクト: FranticFanatic/pennmush
/** 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;
}
コード例 #8
0
ファイル: create.c プロジェクト: FranticFanatic/pennmush
/** Link an exit, room, player, or thing.
 * \verbatim
 * This is the top-level function for @link, which is used to link an
 * exit to a destination, set a player or thing's home, or set a
 * drop-to on a room.
 *
 * Linking an exit usually seizes ownership of the exit and costs 1 penny.
 * 1 penny is also transferred to the former owner.
 * \endverbatim
 * \param player the enactor.
 * \param name the name of the object to link.
 * \param room_name the name of the link destination.
 * \param preserve if 1, preserve ownership and zone data on exit relink.
 * \param pe_info the pe_info to use for any lock checks
 */
void
do_link(dbref player, const char *name, const char *room_name, int preserve,
        NEW_PE_INFO *pe_info)
{
  /* Use this to link to a room that you own.
   * It usually seizes ownership of the exit and costs 1 penny,
   * plus a penny transferred to the exit owner if they aren't you.
   * You must own the linked-to room AND specify it by room number.
   */

  dbref thing;
  dbref room;

  if (!room_name || !*room_name) {
    do_unlink(player, name);
    return;
  }
  if (!IsRoom(player) && GoodObject(Location(player)) &&
      IsExit(Location(player))) {
    notify(player, T("You somehow wound up in a exit. No biscuit."));
    return;
  }
  if ((thing = noisy_match_result(player, name, TYPE_EXIT, MAT_EVERYTHING))
      != NOTHING) {
    switch (Typeof(thing)) {
    case TYPE_EXIT:
      if ((room = check_var_link(room_name)) == NOTHING)
        room = parse_linkable_room(player, room_name, pe_info);
      if (room == NOTHING)
        return;
      if (GoodObject(room) && !can_link_to(player, room, pe_info)) {
        notify(player, T("Permission denied."));
        break;
      }
      /* We may link an exit if it's unlinked and we pass the link-lock
       * or if we control it.
       */
      if (!(controls(player, thing)
            || ((Location(thing) == NOTHING)
                && eval_lock_with(player, thing, Link_Lock, pe_info)))) {
        notify(player, T("Permission denied."));
        return;
      }
      if (preserve && !Wizard(player)) {
        notify(player, T("Permission denied."));
        return;
      }
      /* handle costs */
      if (Owner(thing) == Owner(player)) {
        if (!payfor(player, LINK_COST)) {
          notify_format(player, T("It costs %d %s to link this exit."),
                        LINK_COST, ((LINK_COST == 1) ? MONEY : MONIES));
          return;
        }
      } else {
        if (!payfor(player, LINK_COST + EXIT_COST)) {
          int a = LINK_COST + EXIT_COST;
          notify_format(player, T("It costs %d %s to link this exit."), a,
                        ((a == 1) ? MONEY : MONIES));
          return;
        } else if (!preserve) {
          /* pay the owner for his loss */
          giveto(Owner(thing), EXIT_COST);
          chown_object(player, thing, player, 0);
        }
      }

      /* link has been validated and paid for; do it */
      if (!preserve) {
        Owner(thing) = Owner(player);
        Zone(thing) = Zone(player);
      }
      Location(thing) = room;

      /* notify the player */
      notify_format(player, T("Linked exit #%d to %s"), thing,
                    unparse_object(player, room, AN_UNPARSE));
      break;
    case TYPE_PLAYER:
    case TYPE_THING:
      if ((room =
           noisy_match_result(player, room_name, NOTYPE,
                              MAT_EVERYTHING)) == NOTHING) {
        notify(player, T("No match."));
        return;
      }
      if (IsExit(room)) {
        notify(player, T("That is an exit."));
        return;
      }
      if (thing == room) {
        notify(player, T("You may not link something to itself."));
        return;
      }
      /* abode */
      if (!controls(player, room) && !Abode(room)) {
        notify(player, T("Permission denied."));
        break;
      }
      if (!controls(player, thing)) {
        notify(player, T("Permission denied."));
      } else if (room == HOME) {
        notify(player, T("Can't set home to home."));
      } else {
        /* do the link */
        Home(thing) = room;     /* home */
        if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player)))
          notify(player, T("Home set."));
      }
      break;
    case TYPE_ROOM:
      if ((room = parse_linkable_room(player, room_name, pe_info)) == NOTHING)
        return;
      if ((room != HOME) && (!IsRoom(room))) {
        notify(player, T("That is not a room!"));
        return;
      }
      if (!controls(player, thing)) {
        notify(player, T("Permission denied."));
      } else {
        /* do the link, in location */
        Location(thing) = room; /* dropto */
        notify(player, T("Dropto set."));
      }
      break;
    default:
      notify(player, T("Internal error: weird object type."));
      do_log(LT_ERR, NOTHING, NOTHING,
             "Weird object! Type of #%d is %d", thing, Typeof(thing));
      break;
    }
  }
}
コード例 #9
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);
  }

}