/** Actually change the ownership of something, and fix bits. * \param player the enactor. * \param thing object to change ownership of. * \param newowner new owner for thing. * \param preserve if 1, preserve privileges and don't halt. */ void chown_object(dbref player, dbref thing, dbref newowner, int preserve) { (void) undestroy(player, thing); if (God(player)) { Owner(thing) = newowner; } else { Owner(thing) = Owner(newowner); } /* Don't allow circular zones */ Zone(thing) = NOTHING; if (GoodObject(Zone(newowner))) { dbref tmp; int ok_to_zone = 1; int zone_depth = MAX_ZONES; for (tmp = Zone(Zone(newowner)); GoodObject(tmp); tmp = Zone(tmp)) { if (tmp == thing) { notify(player, T("Circular zone broken.")); ok_to_zone = 0; break; } if (tmp == Zone(tmp)) /* Ran into an object zoned to itself */ break; zone_depth--; if (!zone_depth) { ok_to_zone = 0; notify(player, T("Overly deep zone chain broken.")); break; } } if (ok_to_zone) Zone(thing) = Zone(newowner); } clear_flag_internal(thing, "CHOWN_OK"); if (!preserve || !Wizard(player)) { clear_flag_internal(thing, "WIZARD"); clear_flag_internal(thing, "ROYALTY"); clear_flag_internal(thing, "TRUST"); set_flag_internal(thing, "HALT"); destroy_flag_bitmask("POWER", Powers(thing)); Powers(thing) = new_flag_bitmask("POWER"); do_halt(thing, "", thing); } else { if (preserve == 1 && (newowner != player) && Wizard(thing) && !Wizard(newowner)) { notify_format(player, T("Warning: WIZ flag reset on #%d because " "@CHOWN/PRESERVE is to a non-WIZ flagged third-party."), thing); clear_flag_internal(thing, "WIZARD"); } if (!null_flagmask("POWER", Powers(thing)) || Wizard(thing) || Royalty(thing) || Inherit(thing)) notify_format(player, T("Warning: @CHOWN/PRESERVE on an object (#%d) " "with WIZ, ROY, INHERIT, or @power privileges."), thing); } }
/* 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; }
void CHSInterface::UnsetToggle(int objnum, int flag) #endif { #ifdef PENNMUSH clear_flag_internal(objnum, flag); #endif #ifdef TM3 s_Flags3(objnum, Flags3(objnum) & ~flag); #endif #ifdef MUX s_Flags(objnum, FLAG_WORD3, Flags3(objnum) & ~flag); #endif }
/** 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; }
/** 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; }