/** 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; } }
/* 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; }
// 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; }
dbref db_read(FILE * f, int *db_format, int *db_version, int *db_flags) { dbref i, anum; char ch; const char *tstr; int header_gotten, size_gotten, nextattr_gotten; int read_attribs, read_name, read_zone, read_link, read_key, read_parent; int read_extflags, read_3flags, read_money, read_timestamps, read_new_strings; int read_powers, read_powers_player, read_powers_any; int deduce_version, deduce_name, deduce_zone, deduce_timestamps; int aflags, f1, f2, f3; BOOLEXP *tempbool; header_gotten = 0; size_gotten = 0; nextattr_gotten = 0; g_format = F_UNKNOWN; g_version = 0; g_flags = 0; read_attribs = 1; read_name = 1; read_zone = 0; read_link = 0; read_key = 1; read_parent = 0; read_money = 1; read_extflags = 0; read_3flags = 0; read_timestamps = 0; read_new_strings = 0; read_powers = 0; read_powers_player = 0; read_powers_any = 0; deduce_version = 1; deduce_zone = 1; deduce_name = 1; deduce_timestamps = 1; db_free(); for(i = 0;; i++) { switch (ch = getc(f)) { case '-': /* Misc tag */ switch (ch = getc(f)) { case 'R': /* Record number of players */ mudstate.record_players = getref(f); break; default: (void) getstring_noalloc(f, 0); } break; case '+': /* * MUX and MUSH header */ switch (ch = getc(f)) { /* * 2nd char selects * type */ case 'X': /* * MUX VERSION */ if(header_gotten) { fprintf(stderr, "\nDuplicate MUX version header entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); break; } header_gotten = 1; deduce_version = 0; g_format = F_MUX; g_version = getref(f); /* * Otherwise extract feature flags */ if(g_version & V_GDBM) { read_attribs = 0; read_name = !(g_version & V_ATRNAME); } read_zone = (g_version & V_ZONE); read_link = (g_version & V_LINK); read_key = !(g_version & V_ATRKEY); read_parent = (g_version & V_PARENT); read_money = !(g_version & V_ATRMONEY); read_extflags = (g_version & V_XFLAGS); read_3flags = (g_version & V_3FLAGS); read_powers = (g_version & V_POWERS); read_new_strings = (g_version & V_QUOTED); g_flags = g_version & ~V_MASK; g_version &= V_MASK; deduce_name = 0; deduce_version = 0; deduce_zone = 0; break; case 'S': /* * SIZE */ if(size_gotten) { fprintf(stderr, "\nDuplicate size entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); } else { mudstate.min_size = getref(f); } size_gotten = 1; break; case 'A': /* * USER-NAMED ATTRIBUTE */ anum = getref(f); tstr = getstring_noalloc(f, read_new_strings); if(isdigit(*tstr)) { aflags = 0; while (isdigit(*tstr)) aflags = (aflags * 10) + (*tstr++ - '0'); tstr++; /* * skip ':' */ } else { aflags = mudconf.vattr_flags; } vattr_define((char *) tstr, anum, aflags); break; case 'F': /* * OPEN USER ATTRIBUTE SLOT */ anum = getref(f); break; case 'N': /* * NEXT ATTR TO ALLOC WHEN NO * FREELIST */ if(nextattr_gotten) { fprintf(stderr, "\nDuplicate next free vattr entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); } else { mudstate.attr_next = getref(f); nextattr_gotten = 1; } break; default: fprintf(stderr, "\nUnexpected character '%c' in MUX header near object #%d, ignored.\n", ch, i); tstr = getstring_noalloc(f, 0); } break; case '!': /* * MUX entry/MUSH entry/MUSE non-zoned entry */ if(deduce_version) { g_format = F_MUX; g_version = 1; deduce_name = 0; deduce_zone = 0; deduce_version = 0; } else if(deduce_zone) { deduce_zone = 0; read_zone = 0; } i = getref(f); db_grow(i + 1); if(read_name) { tstr = getstring_noalloc(f, read_new_strings); if(deduce_name) { if(isdigit(*tstr)) { read_name = 0; s_Location(i, atoi(tstr)); } else { s_Name(i, (char *) tstr); s_Location(i, getref(f)); } deduce_name = 0; } else { s_Name(i, (char *) tstr); s_Location(i, getref(f)); } } else { s_Location(i, getref(f)); } /* * ZONE on MUSE databases and some others */ if(read_zone) s_Zone(i, getref(f)); /* * else * * s_Zone(i, NOTHING); */ /* * CONTENTS and EXITS */ s_Contents(i, getref(f)); s_Exits(i, getref(f)); /* * LINK */ if(read_link) s_Link(i, getref(f)); else s_Link(i, NOTHING); /* * NEXT */ s_Next(i, getref(f)); /* * LOCK */ if(read_key) { tempbool = getboolexp(f); atr_add_raw(i, A_LOCK, unparse_boolexp_quiet(1, tempbool)); free_boolexp(tempbool); } /* * OWNER */ s_Owner(i, getref(f)); /* * PARENT: PennMUSH uses this field for ZONE * (which we use as PARENT if we * didn't already read in a * non-NOTHING parent. */ if(read_parent) { s_Parent(i, getref(f)); } else { s_Parent(i, NOTHING); } /* * PENNIES */ if(read_money) /* * if not fix in * unscraw_foreign */ s_Pennies(i, getref(f)); /* * FLAGS */ f1 = getref(f); if(read_extflags) f2 = getref(f); else f2 = 0; if(read_3flags) f3 = getref(f); else f3 = 0; s_Flags(i, f1); s_Flags2(i, f2); s_Flags3(i, f3); if(read_powers) { f1 = getref(f); f2 = getref(f); s_Powers(i, f1); s_Powers2(i, f2); } /* * ATTRIBUTES */ if(read_attribs) { if(!get_list(f, i, read_new_strings)) { fprintf(stderr, "\nError reading attrs for object #%d\n", i); return -1; } } /* * check to see if it's a player */ if(Typeof(i) == TYPE_PLAYER) { c_Connected(i); } break; case '*': /* * EOF marker */ tstr = getstring_noalloc(f, 0); if(strcmp(tstr, "**END OF DUMP***")) { fprintf(stderr, "\nBad EOF marker at object #%d\n", i); return -1; } else { /* * Fix up bizarro foreign DBs */ *db_version = g_version; *db_format = g_format; *db_flags = g_flags; load_player_names(); return mudstate.db_top; } default: fprintf(stderr, "\nIllegal character '%c' near object #%d\n", ch, i); return -1; } } }
/** Create a thing. * \verbatim * This is the top-level function for @create. * \endverbatim * \param player the enactor. * \param name name of thing to create. * \param cost pennies spent in creation. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of new thing, or NOTHING. */ dbref do_create(dbref player, char *name, int cost, char *newdbref) { dbref loc; dbref thing; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; if (*name == '\0') { notify(player, T("Create what?")); return NOTHING; } else if (!ok_name(name, 0)) { notify(player, T("That's a silly name for a thing!")); return NOTHING; } else if (cost < OBJECT_COST) { cost = OBJECT_COST; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } if (can_pay_fees(player, cost)) { /* create the object */ thing = new_object(); /* initialize everything */ set_name(thing, name); if (!IsExit(player)) /* Exits shouldn't have contents! */ Location(thing) = player; else Location(thing) = Source(player); Owner(thing) = Owner(player); Zone(thing) = Zone(player); s_Pennies(thing, cost); Type(thing) = TYPE_THING; Flags(thing) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.thing_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", thing, flagname, 0); } } /* home is here (if we can link to it) or player's home */ if ((loc = Location(player)) != NOTHING && (controls(player, loc) || Abode(loc))) { Home(thing) = loc; /* home */ } else { Home(thing) = Home(player); /* home */ } /* link it in */ if (!IsExit(player)) PUSH(thing, Contents(player)); else PUSH(thing, Contents(Source(player))); /* and we're done */ notify_format(player, T("Created: Object %s."), unparse_dbref(thing)); current_state.things++; local_data_create(thing); queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(thing)); return thing; } return NOTHING; }