/** Transfer pennies to an object's owner. * \param who recipient. * \param pennies amount of pennies to give. */ void giveto(dbref who, int pennies) { if (NoPay(who)) return; /* Giving to a NoPay object or owner */ who = Owner(who); if ((Pennies(who) + pennies) > Max_Pennies(who)) s_Pennies(who, Max_Pennies(who)); else s_Pennies(who, Pennies(who) + pennies); }
/** Debit a player's pennies, if they can afford it. * \param who player to debit. * \param cost number of pennies to debit. * \retval 1 player successfully debited. * \retval 0 player can't afford the cost. */ int payfor(dbref who, int cost) { /* subtract cost from who's pennies */ int tmp; dbref owner; if ((cost == 0) || NoPay(who)) return 1; owner = Owner(who); if ((tmp = Pennies(owner)) >= cost) { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) spent %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } s_Pennies(owner, tmp - cost); return 1; } else { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) tried to spend %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } return 0; } }
/** Can someone pay for something (in cash and quota)? * Does who have enough pennies to pay for something, and if something * is being built, does who have enough quota? Wizards, roys * aren't subject to either. This function not only checks that they * can afford it, but actually charges them. * \param who player attempting to pay. * \param pennies cost in pennies. * \retval 1 who can pay. * \retval 0 who can't pay. */ int can_pay_fees(dbref who, int pennies) { if (Guest(who)) { notify(who, T("Sorry, you aren't allowed to build.")); return 0; } /* check database size -- EVERYONE is subject to this! */ if (DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) { notify(who, T("Sorry, there is no more room in the database.")); return 0; } /* Can they afford it? */ if (!NoPay(who) && (Pennies(Owner(who)) < pennies)) { notify_format(who, T("Sorry, you don't have enough %s."), MONIES); return 0; } /* check building quota */ if (!pay_quota(who, QUOTA_COST)) { notify(who, T("Sorry, your building quota has run out.")); return 0; } /* charge */ payfor(who, pennies); return 1; }
/* 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; }
/** Debit a player's pennies, if they can afford it. * \param who player to debit. * \param cost number of pennies to debit. * \retval 1 player successfully debited. * \retval 0 player can't afford the cost. */ int quiet_payfor(dbref who, int cost) { /* subtract cost from who's pennies */ int tmp; if (NoPay(who)) return 1; who = Owner(who); if ((tmp = Pennies(who)) >= cost) { s_Pennies(who, tmp - cost); return 1; } else return 0; }
dbref create_guest(char *name, char *password) { dbref player; char *buff; if(!Wizard(mudconf.guest_nuker) || !Good_obj(mudconf.guest_nuker)) mudconf.guest_nuker = 1; buff = alloc_lbuf("create_guest"); /* * Make the player. */ player = create_player(name, password, mudconf.guest_nuker, 0, 1); if(player == NOTHING) { log_text("GUEST: failed in create_player\n"); return NOTHING; } /* * Turn the player into a guest. */ s_Guest(player); move_object(player, mudconf.start_room); s_Flags(player, Flags(player) & ~WIZARD); s_Pennies(player, Pennies(mudconf.guest_char)); s_Zone(player, Zone(mudconf.guest_char)); s_Parent(player, Parent(mudconf.guest_char)); /* * Make sure the guest is locked. */ do_lock(player, player, A_LOCK, tprintf("#%d", player), "me"); do_lock(player, player, A_LENTER, tprintf("#%d", player), "me"); /* * Copy all attributes. */ atr_cpy(GOD, player, mudconf.guest_char); free_lbuf(buff); return player; }
void move_object(dbref thing, dbref dest) { dbref src; /* * Remove from the source location */ src = Location(thing); if(src != NOTHING) s_Contents(src, remove_first(Contents(src), thing)); /* * Special check for HOME */ if(dest == HOME) dest = Home(thing); /* * Add to destination location */ if(dest != NOTHING) s_Contents(dest, insert_first(Contents(dest), thing)); else s_Next(thing, NOTHING); s_Location(thing, dest); /* * Look around and do the penny check */ look_in(thing, dest, (LK_SHOWEXIT | LK_OBEYTERSE)); if(isPlayer(thing) && (mudconf.payfind > 0) && (Pennies(thing) < mudconf.paylimit) && (!Controls(thing, dest)) && ((random() % mudconf.payfind) == 0)) { giveto(thing, 1); notify_printf(thing, "You found a %s!", mudconf.one_coin); } }
// Clones an object and returns the HS_DBREF of the new clone. HS_DBREF CHSInterface::CloneThing(HS_DBREF model) { HS_DBREF clone; #ifdef PENNMUSH // No change in code between versions clone = new_object(); // Copy the basic information from the model to the clone. memcpy(REFDB(clone), REFDB(model), sizeof(struct object)); Owner(clone) = Owner(model); Name(clone) = NULL; // NULL-out some memory pointers we didn't really want copied. db[clone].list = NULL; // Now copy the pointer information. atr_cpy(clone, model); Locks(clone) = NULL; clone_locks(model, model, clone); Zone(clone) = Zone(model); Parent(clone) = Parent(model); Flags(clone) = clone_flag_bitmask("FLAG", Flags(model)); set_name(clone, Name(model)); s_Pennies(clone, Pennies(model)); #ifdef CREATION_TIMES /* * We give the clone the same modification time that its * other clone has, but update the creation time */ db[clone].creation_time = time((time_t *) 0); #endif db[clone].contents = db[clone].location = db[clone].next = NOTHING; #endif #if defined(TM3) || defined(MUX) clone = create_obj(Owner(model), Typeof(model), Name(model), Pennies(model)); //atr_free(clone); s_Name(clone, Name(model)); s_Pennies(clone, Pennies(model)); s_Parent(clone, Parent(model)); #ifdef TM3 atr_cpy(Owner(clone), clone, model); s_Flags(clone, Flags(model)); s_Flags2(clone, Flags2(model)); s_Flags3(clone, Flags3(model)); #endif #ifdef MUX atr_cpy(clone, model); s_Flags(clone, FLAG_WORD1, Flags(model)); s_Flags(clone, FLAG_WORD2, Flags2(model)); s_Flags(clone, FLAG_WORD3, Flags3(model)); s_Home(clone, Home(model)); #endif #endif return clone; }
static int db_write_object(FILE * f, dbref i, int db_format, int flags) { ATTR *a; char *got, *as; dbref aowner; int ca, aflags, save, j; BOOLEXP *tempbool; if(!(flags & V_ATRNAME)) putstring(f, Name(i)); putref(f, Location(i)); if(flags & V_ZONE) putref(f, Zone(i)); putref(f, Contents(i)); putref(f, Exits(i)); if(flags & V_LINK) putref(f, Link(i)); putref(f, Next(i)); if(!(flags & V_ATRKEY)) { got = atr_get(i, A_LOCK, &aowner, &aflags); tempbool = parse_boolexp(GOD, got, 1); free_lbuf(got); putboolexp(f, tempbool); if(tempbool) free_bool(tempbool); } putref(f, Owner(i)); if(flags & V_PARENT) putref(f, Parent(i)); if(!(flags & V_ATRMONEY)) putref(f, Pennies(i)); putref(f, Flags(i)); if(flags & V_XFLAGS) putref(f, Flags2(i)); if(flags & V_3FLAGS) putref(f, Flags3(i)); if(flags & V_POWERS) { putref(f, Powers(i)); putref(f, Powers2(i)); } /* * write the attribute list */ if((!(flags & V_GDBM)) || (mudstate.panicking == 1)) { for(ca = atr_head(i, &as); ca; ca = atr_next(&as)) { save = 0; a = atr_num(ca); if(a) j = a->number; else j = -1; if(j > 0) { switch (j) { case A_NAME: if(flags & V_ATRNAME) save = 1; break; case A_LOCK: if(flags & V_ATRKEY) save = 1; break; case A_LIST: case A_MONEY: break; default: save = 1; } } if(save) { got = atr_get_raw(i, j); fprintf(f, ">%d\n", j); putstring(f, got); } } fprintf(f, "<\n"); } return 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; }
static void give_money (dbref giver, dbref recipient, int key, int amount) { dbref aowner; int cost, pcost, rcost, aflags, dpamount; char *str; /* do amount consistency check */ if (amount < 0 && ((!Builder(giver) && !HasPriv(giver,recipient,POWER_STEAL,POWER3,NOTHING)) || DePriv(giver,recipient,DP_STEAL,POWER6,NOTHING))) { notify(giver, unsafe_tprintf("You look through your pockets. Nope, no negative %s.", mudconf.many_coins)); return; } if (!amount) { notify(giver, unsafe_tprintf("You must specify a positive number of %s.", mudconf.many_coins)); return; } dpamount = 0; if (amount < 0) dpamount = DePriv(giver,NOTHING,DP_NOSTEAL,POWER7,POWER_LEVEL_NA); else dpamount = DePriv(giver,NOTHING,DP_NOGOLD,POWER7,POWER_LEVEL_NA); if (dpamount) { if (DPShift(giver)) dpamount--; dpamount = mudconf.money_limit[dpamount]; } else dpamount = -1; if (!Admin(Owner(giver))) { if ((Typeof(recipient) == TYPE_PLAYER) && (Pennies(recipient) + amount > mudconf.paylimit)) { notify(giver, unsafe_tprintf("That player doesn't need that many %s!", mudconf.many_coins)); return; } if ((Typeof(recipient) != TYPE_PLAYER) && (!could_doit(giver, recipient, A_LUSE,1))) { notify(giver, unsafe_tprintf("%s won't take your money.", Name(recipient))); return; } } str = atr_get(Owner(giver), A_PAYLIM, &aowner, &aflags); pcost = atoi(str); free_lbuf(str); if (!Immortal(Owner(giver)) && pcost) { if ((Typeof(recipient) == TYPE_PLAYER) && (amount > 0) && (Pennies(recipient) + amount > pcost)) { notify(giver, unsafe_tprintf("That player doesn't need that many %s!", mudconf.many_coins)); return; } else if (Pennies(recipient) + amount < (-pcost)) { notify(giver,"That player doesn't need that much debt!"); return; } } str = atr_get(Owner(recipient), A_RECEIVELIM, &aowner, &aflags); rcost = atoi(str); free_lbuf(str); if (!Immortal(Owner(giver)) && rcost) { if ((Typeof(recipient) == TYPE_PLAYER) && (amount > 0) && (Pennies(recipient) + amount > rcost)) { notify(giver, unsafe_tprintf("That player doesn't need that many %s!", mudconf.many_coins)); return; } else if (Pennies(recipient) + amount < (-rcost)) { notify(giver,"That player doesn't need that much debt!"); return; } } if (!Immortal(Owner(giver))) { if (dpamount >= 0) { if (amount > 0) { if ((Typeof(recipient) == TYPE_PLAYER) && (Pennies(recipient) + amount > dpamount)) { notify(giver, unsafe_tprintf("That player doesn't need that many %s!", mudconf.many_coins)); return; } else if (amount > dpamount) { notify(giver, "Permission denied."); return; } } else { if ((Typeof(recipient) == TYPE_PLAYER) && (Pennies(recipient) + amount < (-dpamount))) { notify(giver, unsafe_tprintf("That player doesn't need that many %s!", mudconf.many_coins)); return; } else if (amount < (-dpamount)) { notify(giver, "Permission denied."); return; } } } } /* try to do the give */ if (!payfor_give(giver, amount)) { notify(giver, unsafe_tprintf("You don't have that many %s to give!", mudconf.many_coins)); return; } /* Find out cost if an object */ if (Typeof(recipient) == TYPE_THING) { str = atr_pget(recipient, A_COST, &aowner, &aflags); cost = atoi(str); free_lbuf(str); /* Can't afford it? */ if (amount < cost) { notify(giver, "Feeling poor today?"); giveto(giver, amount, NOTHING); return; } /* Negative cost */ if (cost < 0) { return; } } else { cost = amount; } if (!(key & GIVE_QUIET)) { if (amount == 1) { notify(giver, unsafe_tprintf("You give a %s to %s.", mudconf.one_coin, Name(recipient))); notify_with_cause(recipient, giver, unsafe_tprintf("%s gives you a %s.", Name(giver), mudconf.one_coin)); } else { notify(giver, unsafe_tprintf("You give %d %s to %s.", amount, mudconf.many_coins, Name(recipient))); notify_with_cause(recipient, giver, unsafe_tprintf("%s gives you %d %s.", Name(giver), amount, mudconf.many_coins)); } } else { if (amount == 1) { notify(giver, unsafe_tprintf("You give a %s to %s. (quiet)", mudconf.one_coin, Name(recipient))); } else { notify(giver, unsafe_tprintf("You give %d %s to %s. (quiet)", amount, mudconf.many_coins, Name(recipient))); } } /* Report change given */ if((amount - cost) == 1) { notify(giver, unsafe_tprintf("You get 1 %s in change.", mudconf.one_coin)); giveto(giver, 1, NOTHING); } else if (amount != cost) { notify(giver, unsafe_tprintf("You get %d %s in change.", (amount - cost), mudconf.many_coins)); giveto(giver, (amount - cost), NOTHING); } if (pcost && (Pennies(Owner(recipient)) + cost > pcost)) { pcost = pcost - Pennies(Owner(recipient)); if (pcost < 0) pcost = 0; } else pcost = cost; if (!giveto(recipient, pcost, giver)) giveto(giver, cost, NOTHING); /* Transfer the money and run PAY attributes */ /* Rooms should not kick off the PAY attribute */ if ( !isRoom(giver) ) did_it(giver, recipient, A_PAY, NULL, A_OPAY, NULL, A_APAY, (char **)NULL, 0); return; }
void do_kill (dbref player, dbref cause, int key, char *what, char *costchar) { dbref victim; char *buf1, *buf2; int cost; init_match(player, what, TYPE_PLAYER); match_neighbor(); match_me(); match_here(); if (Wizard(player)) { match_player(); match_absolute(); } victim = match_result(); switch (victim) { case NOTHING: notify(player, "I don't see that player here."); break; case AMBIGUOUS: notify(player, "I don't know who you mean!"); break; default: if ((Typeof(victim) != TYPE_PLAYER) && (Typeof(victim) != TYPE_THING)) { notify(player, "Sorry, you can only kill players and things."); break; } if ((Haven(Location(victim)) && !Wizard(player)) || (controls(victim, Location(victim)) && !controls(player, Location(victim))) || Immortal(victim)) { notify(player, "Sorry."); break; } if (key == KILL_SLAY) { if (Builder(player) && Builder(victim)) { notify(player, "Sorry."); break; } } /* go for it */ cost = atoi(costchar); if (key == KILL_KILL) { if (HasPriv(victim,player,POWER_NOKILL,POWER4,NOTHING)) { notify(player, "Sorry."); break; } if (cost < mudconf.killmin) cost = mudconf.killmin; if (cost > mudconf.killmax) cost = mudconf.killmax; /* see if it works */ if (!payfor(player, cost)) { notify(player, unsafe_tprintf("You don't have enough %s.", mudconf.many_coins)); return; } } else { cost = 0; } if (!(((random() % mudconf.killguarantee) < cost) || (key == KILL_SLAY)) || Wizard(victim)) { /* Failure: notify player and victim only */ notify(player, "Your murder attempt failed."); buf1 = alloc_lbuf("do_kill.failed"); sprintf(buf1, "%s tried to kill you!", Name(player)); notify_with_cause(victim, player, buf1); if (Suspect(player)) { strcpy(buf1, Name(player)); if (player == Owner(player)) { raw_broadcast(0, WIZARD, "[Suspect] %s tried to kill %s(#%d).", buf1, Name(victim), victim); } else { buf2 = alloc_lbuf("do_kill.SUSP.failed"); strcpy(buf2, Name(Owner(player))); raw_broadcast(0, WIZARD, "[Suspect] %s <via %s(#%d)> tried to kill %s(#%d).", buf2, buf1, player, Name(victim), victim); free_lbuf(buf2); } } free_lbuf(buf1); break; } /* Success! You killed him */ buf1 = alloc_lbuf("do_kill.succ.1"); buf2 = alloc_lbuf("do_kill.succ.2"); if (Suspect(player)) { strcpy(buf1, Name(player)); if (player == Owner(player)) { raw_broadcast(0, WIZARD, "[Suspect] %s killed %s(#%d).", buf1, Name(victim), victim); } else { strcpy(buf2, Name(Owner(player))); raw_broadcast(0, WIZARD, "[Suspect] %s <via %s(#%d)> killed %s(#%d).", buf2, buf1, player, Name(victim), victim); } } sprintf(buf1, "You killed %s!", Name(victim)); sprintf(buf2, "killed %s!", Name(victim)); if (Typeof(victim) != TYPE_PLAYER) if (halt_que(NOTHING, victim) > 0) if (!Quiet(victim)) notify(Owner(victim), "Halted."); did_it(player, victim, A_KILL, buf1, A_OKILL, buf2, A_AKILL, (char **)NULL, 0); /* notify victim */ sprintf(buf1, "%s killed you!", Name(player)); notify_with_cause(victim, player, buf1); /* Pay off the bonus */ if (key == KILL_KILL) { cost /= 2; /* victim gets half */ if (Pennies(Owner(victim)) < mudconf.paylimit) { sprintf(buf1, "Your insurance policy pays %d %s.", cost, mudconf.many_coins); notify(victim, buf1); giveto(Owner(victim), cost, NOTHING); } else { notify(victim, "Your insurance policy has been revoked."); } } free_lbuf(buf1); free_lbuf(buf2); /* send him home */ move_via_generic(victim, HOME, NOTHING, 0); divest_object(victim); break; } }
/** Change an object's owner. * \verbatim * This implements @chown. * \endverbatim * \param player the enactor. * \param name name of object to change owner of. * \param newobj name of new owner for object. * \param preserve if 1, preserve privileges and don't halt the object. * \param pe_info the pe_info for lock checks */ void do_chown(dbref player, const char *name, const char *newobj, int preserve, NEW_PE_INFO *pe_info) { dbref thing; dbref newowner = NOTHING; long match_flags = MAT_POSSESSION | MAT_HERE | MAT_EXIT | MAT_ABSOLUTE; /* check for '@chown <object>/<atr>=<player>' */ if (strchr(name, '/')) { do_atrchown(player, name, newobj); return; } if (Wizard(player)) match_flags |= MAT_PLAYER; if ((thing = noisy_match_result(player, name, TYPE_THING, match_flags)) == NOTHING) return; if (!*newobj || !strcasecmp(newobj, "me")) { newowner = player; } else { if ((newowner = lookup_player(newobj)) == NOTHING) { notify(player, T("I couldn't find that player.")); return; } } if (IsPlayer(thing) && !God(player)) { notify(player, T("Players always own themselves.")); return; } /* Permissions checking */ if (!chown_ok(player, thing, newowner, pe_info)) { notify(player, T("Permission denied.")); return; } if (IsThing(thing) && !Hasprivs(player) && !(GoodObject(Location(thing)) && (Location(thing) == player))) { notify(player, T("You must carry the object to @chown it.")); return; } if (preserve && !Wizard(player)) { notify(player, T("You cannot @CHOWN/PRESERVE. Use normal @CHOWN.")); return; } /* chowns to the zone master don't count towards fees */ if (!ZMaster(newowner)) { /* Debit the owner-to-be */ if (!can_pay_fees(newowner, Pennies(thing))) { /* not enough money or quota */ if (newowner != player) notify(player, T ("That player doesn't have enough money or quota to receive that object.")); return; } /* Credit the current owner */ giveto(Owner(thing), Pennies(thing)); change_quota(Owner(thing), QUOTA_COST); } chown_object(player, thing, newowner, preserve); notify(player, T("Owner changed.")); }