/** 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; } }
/** Unlock a lock (user interface). * \verbatim * This implements @unlock. * \endverbatim * \param player the enactor. * \param name name of object to unlock. * \param type type of lock to unlock. */ void do_unlock(dbref player, const char *name, lock_type type) { dbref thing; lock_type real_type; /* check for '@unlock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "off"); return; } if ((thing = match_controlled(player, name)) != NOTHING) { if ((real_type = check_lock_type(player, thing, type)) != NULL) { if (getlock(thing, real_type) == TRUE_BOOLEXP) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s (already) unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); } else if (delete_lock(player, thing, real_type)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else notify(player, T("Permission denied.")); } } }
/** Take an action on an object and trigger attributes. * \verbatim * executes the @attr, @oattr, @aattr for a command - gives a message * to the enactor and others in the room with the enactor, and executes * an action. We optionally load pe_regs into the queue. * \endverbatim * * \param player the enactor. * \param thing object being triggered. * \param what message attribute for enactor. * \param def default message to enactor. * \param owhat message attribute for others. * \param odef default message to others. * \param awhat action attribute to trigger. * \param loc location in which action is taking place. * \param pe_regs the pe_regs arguments for the evaluation/queueing * \param flags flags controlling type of interaction involved. * \retval 0 no attributes were present, only defaults were used if given. * \retval 1 some attributes were evaluated and used. */ int real_did_it(dbref player, dbref thing, const char *what, const char *def, const char *owhat, const char *odef, const char *awhat, dbref loc, PE_REGS *pe_regs, int flags, int an_flags) { char buff[BUFFER_LEN], *bp; int attribs_used = 0; NEW_PE_INFO *pe_info = NULL; ufun_attrib ufun; if (!pe_info) { pe_info = make_pe_info("pe_info-real_did_it2"); } loc = (loc == NOTHING) ? Location(player) : loc; /* only give messages if the location is good */ if (GoodObject(loc)) { /* message to player */ if (what && *what) { if (fetch_ufun_attrib (what, thing, &ufun, UFUN_LOCALIZE | UFUN_REQUIRE_ATTR | UFUN_IGNORE_PERMS)) { attribs_used = 1; if (!call_ufun(&ufun, buff, thing, player, pe_info, pe_regs) && buff[0]) notify_by(thing, player, buff); } else if (def && *def) notify_by(thing, player, def); } /* message to neighbors */ if (!DarkLegal(player)) { if (owhat && *owhat && fetch_ufun_attrib(owhat, thing, &ufun, UFUN_LOCALIZE | UFUN_REQUIRE_ATTR | UFUN_IGNORE_PERMS | UFUN_NAME)) { attribs_used = 1; if (!call_ufun_int (&ufun, buff, thing, player, pe_info, pe_regs, (void *) AName(player, an_flags, NULL)) && buff[0]) notify_except2(player, loc, player, thing, buff, flags); } else if (odef && *odef) { bp = buff; safe_format(buff, &bp, "%s %s", AName(player, an_flags, NULL), odef); *bp = '\0'; notify_except2(player, loc, player, thing, buff, flags); } } } if (pe_info) { free_pe_info(pe_info); } if (awhat && *awhat) attribs_used = queue_attribute_base(thing, awhat, player, 0, pe_regs, 0) || attribs_used; return attribs_used; }
/** 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; }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; /* check for '@lock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "on"); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, LF_DEFAULT)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else { notify(player, T("Permission denied.")); /* Done by a failed add_lock() // free_boolexp(key); */ } } else free_boolexp(key); } }
/** Autoreply messages for pages (HAVEN, IDLE, AWAY). * \param player the paging player. * \param target the paged player. * \param type type of message to return. * \param message name of attribute containing the message. * \param def default message to return. */ void page_return(dbref player, dbref target, const char *type, const char *message, const char *def) { char buff[BUFFER_LEN]; struct tm *ptr; if (message && *message) { if (call_attrib(target, message, buff, player, NULL, NULL)) { if (*buff) { ptr = (struct tm *) localtime(&mudtime); notify_format(player, T("%s message from %s: %s"), type, AName(target, AN_SYS, NULL), buff); if (!Haven(target)) notify_format(target, T("[%d:%02d] %s message sent to %s."), ptr->tm_hour, ptr->tm_min, type, AName(player, AN_SYS, NULL)); } } else if (def && *def) notify(player, def); } }
/** Set flags on a lock (user interface). * \verbatim * This implements @lset. * \endverbatim * \param player the enactor. * \param what string in the form obj/lock. * \param flags list of flags to set. */ void do_lset(dbref player, char *what, char *flags) { dbref thing; lock_list *l; char *lname; privbits flag; bool unset = 0; if ((lname = strchr(what, '/')) == NULL) { notify(player, T("No lock name given.")); return; } *lname++ = '\0'; if ((thing = match_controlled(player, what)) == NOTHING) return; if (*flags == '!') { unset = 1; flags++; } if (string_to_lockflag(player, flags, &flag) < 0) { notify(player, T("Unrecognized lock flag.")); return; } l = getlockstruct_noparent(thing, lname); if (!l || !Can_Read_Lock(player, thing, L_TYPE(l))) { notify(player, T("No such lock.")); return; } if (!can_write_lock(player, thing, l)) { notify(player, T("Permission denied.")); return; } if (unset) L_FLAGS(l) &= ~flag; else L_FLAGS(l) |= flag; if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify_format(player, "%s/%s - %s.", AName(thing, AN_SYS, NULL), L_TYPE(l), unset ? T("lock flags unset") : T("lock flags set")); if (!IsPlayer(thing)) ModTime(thing) = mudtime; }
/** The whisper command. * \param player the enactor. * \param arg1 name of the object to whisper to. * \param arg2 message to whisper. * \param noisy if 1, others overhear that a whisper has occurred. * \param pe_info the pe_info for evaluating interact locks */ void do_whisper(dbref player, const char *arg1, const char *arg2, int noisy, NEW_PE_INFO *pe_info) { dbref who; int key; const char *gap; char *tbuf, *tp; char *p; dbref good[100]; int gcount = 0; const char *head; int overheard; char *current; const char **start; char sname[BUFFER_LEN]; if (!arg1 || !*arg1) { notify(player, T("Whisper to whom?")); return; } if (!arg2 || !*arg2) { notify(player, T("Whisper what?")); return; } tp = tbuf = (char *) mush_malloc(BUFFER_LEN, "string"); if (!tbuf) mush_panic("Unable to allocate memory in do_whisper"); overheard = 0; head = arg1; start = &head; /* Figure out what kind of message */ gap = " "; switch (*arg2) { case SEMI_POSE_TOKEN: gap = ""; case POSE_TOKEN: key = 1; arg2++; break; default: key = 2; break; } *tp = '\0'; /* Make up a list of good and bad names */ while (head && *head) { current = next_in_list(start); who = match_result(player, current, TYPE_PLAYER, MAT_NEAR_THINGS | MAT_CONTAINER); if (!GoodObject(who) || !can_interact(player, who, INTERACT_HEAR, pe_info)) { safe_chr(' ', tbuf, &tp); safe_str_space(current, tbuf, &tp); if (GoodObject(who)) notify_format(player, T("%s can't hear you."), AName(who, AN_SYS, NULL)); } else { /* A good whisper */ good[gcount++] = who; if (gcount >= 100) { notify(player, T("Too many people to whisper to.")); break; } } } *tp = '\0'; if (*tbuf) notify_format(player, T("Unable to whisper to:%s"), tbuf); if (!gcount) { mush_free(tbuf, "string"); return; } /* Drunk wizards... */ if (Dark(player)) noisy = 0; /* Set up list of good names */ tp = tbuf; safe_str(T(" to "), tbuf, &tp); for (who = 0; who < gcount; who++) { if (noisy && (get_random32(0, 100) < (uint32_t) WHISPER_LOUDNESS)) overheard = 1; safe_itemizer(who + 1, (who == gcount - 1), ",", T("and"), " ", tbuf, &tp); safe_str(AName(good[who], AN_SAY, NULL), tbuf, &tp); } *tp = '\0'; if (key == 1) { notify_format(player, (gcount > 1) ? T("%s sense: %s%s%s") : T("%s senses: %s%s%s"), tbuf + 4, AName(player, AN_SAY, NULL), gap, arg2); p = tprintf("You sense: %s%s%s", AName(player, AN_SAY, NULL), gap, arg2); } else { notify_format(player, T("You whisper, \"%s\"%s."), arg2, tbuf); p = tprintf(T("%s whispers%s: %s"), AName(player, AN_SAY, NULL), gcount > 1 ? tbuf : "", arg2); } strcpy(sname, AName(player, AN_SAY, NULL)); for (who = 0; who < gcount; who++) { notify_must_puppet(good[who], p); if (Location(good[who]) != Location(player)) overheard = 0; } if (overheard) { dbref first = Contents(Location(player)); if (!GoodObject(first)) return; p = tprintf(T("%s whispers%s."), sname, tbuf); DOLIST(first, first) { overheard = 1; for (who = 0; who < gcount; who++) { if ((first == player) || (first == good[who])) { overheard = 0; break; } } if (overheard) notify_noecho(first, p); } }