Ejemplo n.º 1
0
/** 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.
 */
void
do_open(dbref player, const char *direction, char **links)
{
  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;
    }
  }

  forward = do_real_open(player, direction, links[1], source);
  if (links[2] && GoodObject(forward) && GoodObject(Location(forward))) {
    char sourcestr[SBUF_LEN];   /* SBUF_LEN is the size used by unparse_dbref */
    if (!GoodObject(source)) {
      if (IsRoom(player)) {
        source = player;
      } else if (IsExit(player)) {
        source = Home(player);
      } else {
        source = Location(player);
      }
    }
    strcpy(sourcestr, unparse_dbref(source));
    do_real_open(player, links[2], sourcestr, Location(forward));
  }
}
Ejemplo n.º 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));
}
Ejemplo n.º 3
0
/** Return the first object near another object that is visible to a player.
 *
 * BEWARE:
 *
 * first_visible() does not behave as intended. It _should_ return the first
 * object in `thing' that is !DARK. However, because of the controls() check
 * the function will return a DARK object if the player owns it.
 *
 * The behavior is left as is because so many functions in fundb.c rely on
 * the incorrect behavior to return expected values. The lv*() functions
 * also make rewriting this fairly pointless.
 *
 * \param player the looker.
 * \param thing an object in the location to be inspected.
 * \return dbref of first visible object or NOTHING.
 */
dbref
first_visible(dbref player, dbref thing)
{
  int lck = 0;
  int ldark;
  dbref loc;

  if (!GoodObject(thing) || IsRoom(thing))
    return NOTHING;
  loc = IsExit(thing) ? Source(thing) : Location(thing);
  if (!GoodObject(loc))
    return NOTHING;
  ldark = IsPlayer(loc) ? Opaque(loc) : Dark(loc);

  while (GoodObject(thing)) {
    if (can_interact(thing, player, INTERACT_SEE, NULL)) {
      if (DarkLegal(thing) || (ldark && !Light(thing))) {
        if (!lck) {
          if (See_All(player) || (loc == player) || controls(player, loc))
            return thing;
          lck = 1;
        }
        if (controls(player, thing))    /* this is what causes DARK objects to show */
          return thing;
      } else {
        return thing;
      }
    }
    thing = Next(thing);
  }
  return thing;
}
Ejemplo n.º 4
0
/* Show the 'Obvious Exits' list for a room. Used in 'look' and 'examine'.
 * \param player The player looking
 * \param loc room whose exits we're showing
 * \param exit_name "Obvious Exits" string
 * \param pe_info the pe_info to use for evaluating EXITFORMAT and interact locks
 */
static void
look_exits(dbref player, dbref loc, const char *exit_name, NEW_PE_INFO *pe_info)
{
  dbref thing;
  char *tbuf1, *tbuf2, *nbuf;
  char *s1, *s2;
  char *p;
  int exit_count, this_exit, total_count;
  int texits;
  ufun_attrib ufun;
  PUEBLOBUFF;

  /* make sure location is a room */
  if (!IsRoom(loc))
    return;

  tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
  tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string");
  nbuf = (char *) mush_malloc(BUFFER_LEN, "string");
  if (!tbuf1 || !tbuf2 || !nbuf)
    mush_panic("Unable to allocate memory in look_exits");
  s1 = tbuf1;
  s2 = tbuf2;
  texits = exit_count = total_count = 0;
  this_exit = 1;

  if (fetch_ufun_attrib
      ("EXITFORMAT", loc, &ufun, UFUN_IGNORE_PERMS | UFUN_REQUIRE_ATTR)) {
    char *arg, *buff, *bp;
    PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "look_exits");

    arg = (char *) mush_malloc(BUFFER_LEN, "string");
    buff = (char *) mush_malloc(BUFFER_LEN, "string");
    if (!arg || !buff)
      mush_panic("Unable to allocate memory in look_exits");

    bp = arg;
    DOLIST(thing, Exits(loc)) {
      if (((Light(loc) || Light(thing)) || !(Dark(loc) || Dark(thing)))
          && can_interact(thing, player, INTERACT_SEE, pe_info)) {
        if (bp != arg)
          safe_chr(' ', arg, &bp);
        safe_dbref(thing, arg, &bp);
      }
    }
    *bp = '\0';
    pe_regs_setenv_nocopy(pe_regs, 0, arg);

    call_ufun(&ufun, buff, player, player, pe_info, pe_regs);

    pe_regs_free(pe_regs);
    notify_by(loc, player, buff);
    mush_free(tbuf1, "string");
    mush_free(tbuf2, "string");
    mush_free(nbuf, "string");
    mush_free(arg, "string");
    mush_free(buff, "string");
    return;
  }
Ejemplo n.º 5
0
/** Are two objects near each other?
 * Returns 1 if obj1 is "nearby" object2. "Nearby" is a commutative
 * relation defined as:
 *   obj1 is in the same room as obj2, obj1 is being carried by
 *   obj2, or obj1 is carrying obj2.
 * Returns 0 if object isn't nearby or the input is invalid.
 * \param obj1 first object.
 * \param obj2 second object.
 * \retval 1 the objects are near each other.
 * \retval 0 the objects are not near each other.
 */
int
nearby(dbref obj1, dbref obj2)
{
  dbref loc1, loc2;

  if (!GoodObject(obj1) || !GoodObject(obj2))
    return 0;
  if (IsRoom(obj1) && IsRoom(obj2))
    return 0;
  loc1 = where_is(obj1);
  if (loc1 == obj2)
    return 1;
  loc2 = where_is(obj2);
  if ((loc2 == obj1) || (loc2 == loc1))
    return 1;
  return 0;
}
Ejemplo n.º 6
0
/* Clone an object. The new object is owned by the cloning player */
static dbref
clone_object(dbref player, dbref thing, const char *newname, int preserve)
{
  dbref clone;

  clone = new_object();

  Owner(clone) = Owner(player);
  Name(clone) = NULL;
  if (newname && *newname)
    set_name(clone, newname);
  else
    set_name(clone, Name(thing));
  s_Pennies(clone, Pennies(thing));
  AttrCount(clone) = 0;
  List(clone) = NULL;
  Locks(clone) = NULL;
  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 {
    Powers(clone) = clone_flag_bitmask("POWER", Powers(thing));
    Warnings(clone) = Warnings(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."));
  }
  /* We give the clone the same modification time that its
   * other clone has, but update the creation time */
  ModTime(clone) = ModTime(thing);
  CreTime(clone) = mudtime;
  Type(clone) = Type(thing);

  Contents(clone) = Location(clone) = Next(clone) = NOTHING;
  if (IsRoom(thing))
    Exits(clone) = NOTHING;
  else
    Home(clone) = Home(thing);
  atr_cpy(clone, thing);

  queue_event(player, "OBJECT`CREATE", "%s,%s",
              unparse_objid(clone), unparse_objid(thing));
  return clone;

}
Ejemplo n.º 7
0
/** Given an exit, find the room that is its source through brute force.
 * This is used in pathological cases where the exit's own source
 * element is invalid.
 * \param door dbref of exit to find source of.
 * \return dbref of exit's source room, or NOTHING.
 */
dbref
find_entrance(dbref door)
{
  dbref room;
  dbref thing;
  for (room = 0; room < db_top; room++) {
    if (IsRoom(room)) {
      thing = Exits(room);
      while (thing != NOTHING) {
        if (thing == door)
          return room;
        thing = Next(thing);
      }
    }
  }
  return NOTHING;
}
Ejemplo n.º 8
0
void SetItData(short u, ITEM *x, short a, short n)
{
	if(u==-1)
		u=ParsingPersona;
	if((IsPlayer(x))&&(x!=Me()))
	{
		ParserData[u].pa_Them[0]=a;
		ParserData[u].pa_Them[1]=n;
		if(PlayerOf(x)->pl_Flags&PL_MALE)
		{
			ParserData[u].pa_Him[0]=a;
			ParserData[u].pa_Him[1]=n;
			return;
		}
		if(PlayerOf(x)->pl_Flags&PL_FEMALE)
		{
			ParserData[u].pa_Her[0]=a;
			ParserData[u].pa_Her[1]=n;
			return;
		}
		ParserData[u].pa_It[0]=a;
		ParserData[u].pa_It[1]=n;
		return;
	}
	if(IsObject(x))
	{
		if((ObjectOf(x)->ob_Flags&OB_NOIT)==0)
		{
			ParserData[u].pa_It[0]=a;
			ParserData[u].pa_It[1]=n;
		}
	}
	if(IsRoom(x))
	{
		ParserData[u].pa_There[0]=a;
		ParserData[u].pa_There[1]=n;
	}
}
Ejemplo n.º 9
0
static void
ct_exit(dbref player, dbref i, warn_type flags)
{
    dbref j, src, dst;
    int count = 0;
    int lt;

    /* i must be an exit, must be in a valid room, and must lead to a
     * different room
     * Remember, for exit i, Exits(i) = source room
     * and Location(i) = destination room
     */

    dst = Destination(i);
    if ((flags & W_EXIT_UNLINKED) && (dst == NOTHING))
        complain(player, i, "exit-unlinked",
                 T("exit is unlinked; anyone can steal it"));

    if ((flags & W_EXIT_UNLINKED) && dst == AMBIGUOUS) {
        ATTR *a;
        const char *var = "DESTINATION";
        a = atr_get(i, "DESTINATION");
        if (!a)
            a = atr_get(i, "EXITTO");
        if (a)
            var = "EXITTO";
        if (!a)
            complain(player, i, "exit-unlinked",
                     T("Variable exit has no %s attribute"), var);
        else {
            const char *x = atr_value(a);
            if (!x || !*x)
                complain(player, i, "exit-unlinked",
                         T("Variable exit has empty %s attribute"), var);
        }
    }

    if (!Dark(i)) {
        if (flags & W_EXIT_MSGS) {
            lt = warning_lock_type(getlock(i, Basic_Lock));
            if ((lt & W_UNLOCKED) &&
                    (!atr_get(i, "OSUCCESS") || !atr_get(i, "ODROP") ||
                     !atr_get(i, "SUCCESS")))
                complain(player, i, "exit-msgs",
                         T("possibly unlocked exit missing succ/osucc/odrop"));
            if ((lt & W_LOCKED) && !atr_get(i, "FAILURE"))
                complain(player, i, "exit-msgs",
                         T("possibly locked exit missing fail"));
        }
        if (flags & W_EXIT_DESC) {
            if (!atr_get(i, "DESCRIBE"))
                complain(player, i, "exit-desc", T("exit is missing description"));
        }
    }
    src = Source(i);
    if (!GoodObject(src) || !IsRoom(src))
        return;
    if (src == dst)
        return;
    /* Don't complain about exits linked to HOME or variable exits. */
    if (!GoodObject(dst))
        return;

    for (j = Exits(dst); GoodObject(j); j = Next(j))
        if (Location(j) == src) {
            if (!(flags & W_EXIT_MULTIPLE))
                return;
            else
                count++;
        }
    if ((count == 0) && (flags & W_EXIT_ONEWAY))
        complain(player, i, "exit-oneway", T("exit has no return exit"));
    else if ((count > 1) && (flags & W_EXIT_MULTIPLE))
        complain(player, i, "exit-multiple",
                 T("exit has multiple (%d) return exits"), count);
}
Ejemplo n.º 10
0
/** 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.
 * \return dbref of the new exit, or NOTHING.
 */
dbref
do_real_open(dbref player, const char *direction, const char *linkto,
             dbref pseudo)
{
  dbref loc =
    (pseudo !=
     NOTHING) ? pseudo : (IsExit(player) ? Source(player) : (IsRoom(player) ?
                                                             player :
                                                             Location(player)));
  dbref new_exit;
  char *flaglist, *flagname;
  char flagbuff[BUFFER_LEN];
  char *name = NULL;
  char *alias = NULL;

  if (!command_check_byname(player, "@dig")) {
    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) < 1) {
    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 (!Open_Anywhere(player) && !controls(player, loc)) {
    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);
    if (alias && *alias != ALIAS_DELIMITER)
      atr_add(new_exit, "ALIAS", alias, player, 0);
    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)
      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);
      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;
}
Ejemplo n.º 11
0
/** 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;

}
Ejemplo n.º 12
0
/** 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.
 */
void
do_link(dbref player, const char *name, const char *room_name, int preserve)
{
  /* 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);
      if (room == NOTHING)
        return;
      if (GoodObject(room) && !can_link_to(player, room)) {
        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(player, thing, Link_Lock)))) {
        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));
      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)) == 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;
    }
  }
}
Ejemplo n.º 13
0
ITEM *Clone_Item(ITEM *i, short f)	/* 1=true dup 0=normal dup */
{
	DUP *d;
	ITEM *n=CreateItem(NameOf(i),i->it_Adjective,i->it_Noun);
	SUB *s;
	n->it_ActorTable=i->it_ActorTable;
	n->it_ActionTable=i->it_ActionTable;
	n->it_State=i->it_State;
	n->it_Class=i->it_Class;
	n->it_Perception=i->it_Perception;
	n->it_SubjectTable=NULL;
	n->it_ObjectTable=NULL;
	n->it_DaemonTable=NULL;
	/* Cheat: We want the clone to behave as the original, but that
	   would mean copying the tables which is slow and uses lots of
	   memory. We use the new subclassing feature to cheat and make
	   the original superclass of the clones. */
	LockItem(i);
	n->it_Superclass=i;

	if(IsRoom(i))
		Clone_Room(n,i);
	if(IsPlayer(i))
		Clone_Player(n,i);
	if(IsObject(i))
		Clone_Object(n,i);
	if(FindSub(i,KEY_GENEXIT))
		Clone_GenExit(n,i);
	s=i->it_Properties;
	while(s)
	{
		switch(s->pr_Key)
		{
		case KEY_MSGEXIT:Clone_MsgExit(n,(MSGEXIT *)s);
				 break;
		case KEY_CONTAINER:
				Clone_Container(n,(CONTAINER *)s);
				break;
		case KEY_CHAIN:
				Clone_Chain(n,(CHAIN *)s);
				break;
		case KEY_USERFLAG:
		case KEY_USERFLAG2:
				Clone_UserFlag(n,(USERFLAG *)s);
				break;
		case KEY_INHERIT:
				Clone_Inherit(n,(INHERIT *)s);
				break;
		case KEY_USERTEXT:
				Clone_UserText(i,n);
				break;
		case KEY_INOUTHERE:
				SetInMsg(n,TextOf(((INOUTHERE *)s)->io_InMsg));
				SetOutMsg(n,TextOf(((INOUTHERE *)s)->io_OutMsg));
				SetHereMsg(n,TextOf(((INOUTHERE *)s)->io_HereMsg));
				break;
		case KEY_CONDEXIT:
				MakeCondExit(n,((CONDEXIT *)s)->ce_Dest,
					((CONDEXIT *)s)->ce_Table,
					((CONDEXIT *)s)->ce_ExitNumber);
				break;
		}
		s=s->pr_Next;
	}
	if(!f)
	{
		d=(DUP *)AllocSub(n,KEY_DUPED,sizeof(DUP));
		d->du_Master=i;
		LockItem(i);
	}
	return(n);
}