This object allows for the description to change on the fly as it is "consumed". The Drinkable and Edible versions are descendents of this object with the consume verb aliased to drink and eat type commands. Please read the help on this object for instructions. I have modified this object to work in enCore v4 MOOs, it originally was programmed by somebody at LambdaMOO I believe. I'm afraid I no longer have the credits for this object if anybody has them please let me know! KRJ June 10, 2007 ========================== Generic Consumable Object @create $thing named Generic Consumable:Generic Consumable,gc @prop #xxx."chunks" 1 r @prop #xxx."maxChunks" 5 rc @prop #xxx."consume_msgs" {} rc ;;#xxx.("consume_msgs") = {"You consume a bit of the %t."} @prop #xxx."home" 0 rc @prop #xxx."lastConsume_msgs" {} rc ;;#xxx.("lastConsume_msgs") = {"You finish off the %t, and boy is it good!"} @prop #xxx."returnDelay" 60 rc @prop #xxx."evaporate_msgs" {} rc ;;#xxx.("evaporate_msgs") = {"The %t evaporates in a dusty puff of smoke. It came, it was consumed, it's going home."} @prop #xxx."alreadyEmpty_msgs" {} rc ;;#xxx.("alreadyEmpty_msgs") = {"Too late, friend. There is no more %t for you."} @prop #xxx."notHolding_msg" "You're not holding the %t." rc @prop #xxx."help_msg" {} rc ;;#xxx.("help_msg") = {"", " Generic Consumable", " NOTE: Normally you will want to use the generic drinkable or the generic edible.", "__________________________ ____________________________________________________", "", " Eat, drink, and be merry, for tomorrow you may lag.", "", " I thought quite a bit about this object, and finally decided to make it difficult to use. In order to keep it interesting, there are several lists of messages that your really must set. So without further ado, here they are:", "", " Um.. okay, a little ado. I decided against having them recycle themselves, because the dispensing would be a bother, and because players with low quota would find it a pain.", " -- The Unknown Creator. Someone (Shig? my memory grows hazy. Mona? Help me, Mona!) at Freegate.", "", "I've now forgotten who did this part. I've made quite a few modifications for use on Valhalla, mostly to make it easier to use, and to talk to the consumer as well as everyone watching the consumer get stuffed/drunk. Oh, and the auto-refill mode.", " -- Jerry Stratton (jerry@teetot.acusd.edu, CapVideo@valhalla)", "", " .maxChunks", " .home", " .returnDelay", " After .returnDelay seconds after the consumable is emptied, it returns home (if it isn't already home). Additionally, if it is .auto_Refill type 2, it is automatically refilled to .maxChunks.", "", " .firstdescriptions_msgs", " .middescription_msgs", " .lastdescriptions_msgs", " An additional description of the consumable when full. This is added on a separate line after .description. These properties are checked in this order, until one with a valid line is found: .fulldescriptions_msg, .lastdescriptions_msg, and .description_msg (which had *better* have a valid line). If .firstdescriptions_msgs or .lastdescriptions_msgs have more than one line, the second line goes for the second chunk (or the second-to-last chunk), the third line for the third chunk, etc. If .middescriptions_msgs has more than one line, a line is chosen at random.", "", " .firstConsume_msgs", " .ofirstConsume_msgs", " .consume_msgs", " .oconsume_msgs", " .lastConsume_msgs", " .olastConsume_msgs", " A list of messages seen when a chunk is consumed. Messages are chosen randomly if there are more than one line in the message, and the same line number is used for consume (player) and oconsume (others). 'lastConsume' is used for the last chunk that is eaten. 'first' and 'last' are for the first chunk (.chunk==maxChunk) and last chunk (.chunk==1).", "", " .evaporate_msgs", " .appear_msgs", " A list of messages seen when the empty food evaporates and re-appears home. The same line number is used for .appear as for .evaporate, if possible.", "", " .alreadyEmpty_msgs", " .oalreadyEmpty_msgs", " If somebody tries to eat an already empty consumable, these messages are displayed. One message is chosen randomly.", "", " .must_take", " .notHolding_msg", " If .must_take is '1', then anyone who is not holding the consumable who tries to consume it will get the .notHolding_msg.", "Setting: @SET .MUST_TAKE TO 1 or 0", " @NOTHOLDING IS \"The message.", "", " .condiment_type", " .condiment_msgs", " .ocondiment_msgs", " Condiment _type_ is 0 if only the owner-specified condiments can be used, and 1 if any condiments can be used. Condiment messages are a message for each condiment (line 1 is used if *any* condiment can be used). Use ADDCONDIM and RMCONDIM any TO this to add or remove condiments from the approved list.", "", " .auto_Refill", " .refill_msgs", " If .auto_Refill is 0, the item is not refilled when consumed. If .auto_Refill is 1, the item is continually replenished--it never goes empty. If .auto_Refill is 2, the item gets re-filled once it goes empty, after .returnDelay seconds. Additionally, for option 2, a random line from .refill_msgs is displayed in the location where the object returns. .refill_msgs is also used when the owner does \"Refill\".", "Setting auto_refill: @SET .AUTO_REFILL TO 0, 1, or 2", "", " .save_line", " Ignore the man behind the curtain. This property is used to allow 'send_message' to talk to itself between calls.", "", "VERBS", " EAT/DRINK this", " The standard verb is 'consume', but you can't use it. The generic edible has \"eat/bite/nibble\" and the generic drinkable has \"drink/sip\". Important messages: firstConsume_msgs, ofirstConsume_msgs; lastConsume_msgs, olastConsume_msgs; consume_msgs, oconsume_msgs; alreadyEmpty_msgs, oalreadyEmpty_msgs.", " I see from the code that in theory you can be a pig and consume more than one chunk at a time. I don't see how this works.", "", " ADD/SPRINKLE/SPREAD/PUT/SLATHER/POUR/SQUEEZE condiment ON this", " Puts condiments on the consumable. Relevant properties: .condiment_type, .condiments, .condiment_msgs", " REFILL/REPLACE this", " Only the owner may refill a consumable. Sets 'chunks' to 'maxChunks'. Important messages: refill_msgs.", "", " @LOOK this", " Gives information about the settable numeric and object id properties.", "", "SEND_MESSAGE(property_name) ==> string", " 1. If the property is a list, one is chosen at random *unless* .save_line is greater than 0, in which case item .save_line is used.", " 2. If .save_line is -1, it sets .save_line to the number of the item chosen.", " 3. $string_utils:pronoun_sub() is called to do pronoun substitution. But *first*, it does it's own substitution, as follows:", " &chunks ==> the number of chunks left, as a digit.", " &consumed ==> the number of chunks consumed, as a digit.", " &full ==> the number of chunks when full.", " &condiment ==> the condiment being used on the chunk.", " &condiments ==> all the condiments in the list.", " &verb ==> whatever verb the consumer typed.", " &food ==> the contents of .food_msg", " & ==> an ampersand.", " &plural{string0,string1,...,string_many} ==> the string corresponding to the number of chunks left. The last string is used for all numbers greater than that as well. Simply using &plural gives \"s\" for 0 and 2 or more, and nothing for 1.", " &pluralc and &pluralf are &plural for 'consumed' and for 'full."} @prop #xxx."must_take" 0 rc @prop #xxx."auto_refill" 0 rc @prop #xxx."refill_msgs" {} rc ;;#xxx.("refill_msgs") = {"A scantily clad frog refills the %t.", "A strange pig arrives and refills the %t, asking if you've seen a scantily clad frog."} @prop #xxx."appear_msgs" {} rc ;;#xxx.("appear_msgs") = {"A %t appears before your eyes."} @prop #xxx."oalreadyEmpty_msgs" {} rc ;;#xxx.("oalreadyEmpty_msgs") = {"%N looks forlornly at the remains of %p %t."} @prop #xxx."oconsume_msgs" {} rc ;;#xxx.("oconsume_msgs") = {"%N consumes a bit of the %t."} @prop #xxx."olastConsume_msgs" {} rc ;;#xxx.("olastConsume_msgs") = {"%N finishes off the %t, smacking %p lips."} @prop #xxx."firstConsume_msgs" "You dig into the %t." rc @prop #xxx."ofirstConsume_msgs" "%N digs into the %t." rc @prop #xxx."save_line" 0 r @prop #xxx."firstdescriptions_msgs" {} rc ;;#xxx.("firstdescriptions_msgs") = {"A full %t.", "An almost full %t."} @prop #xxx."lastdescriptions_msgs" {} rc ;;#xxx.("lastdescriptions_msgs") = {"An empty %t... looks like someone enjoyed it!", "An almost empty %t. Better hurry if you want some, %N."} @prop #xxx."middescriptions_msgs" {} rc ;;#xxx.("middescriptions_msgs") = {"There &plural{are,is,are} &chunks chunk&plural left.", "There &pluralc{are,is,are} &consumed chunk&pluralc gone.", "There &pluralc{are,is,are} &pluralc{one,two,three,several} chunk&pluralc gone out of &full chunk&pluralf total."} @prop #xxx."atlook_msg" {} rc ;;#xxx.("atlook_msg") = {"%T:", " Home: %[thome].", " Use '@SET %t.HOME TO ' to change.", " Chunks left: &chunks.", " Use 'REPLACE %t' to restore it.", " Chunks When Full: &full chunk&pluralf.", " Use '@SET %t.MAXCHUNKS TO ' to change this.", " Auto Refill Type: %[tauto_Refill].", " Use '@SET %t.AUTO_REFILL TO <0, 1, or 2>' to change.", " 0=Manual Refill; 1=Continually Replenished; 2=Automatic Refill", " Delay Before Refill: %[treturnDelay] second(s).", " Use '@SET %t.RETURNDELAY TO ' to change.", " Do consumers have to hold it? %[tmust_take].", " Use '@SET %t.MUST_TAKE TO <0 or 1>' to change.", " 1 = Yes; 0 = No.", " Condiments Allowed: %[tcondiment_type].", " Use '@SET %t.CONDIMENT_TYPE TO <0 or 1>' to change.", " 1 = Any, 0 = Only those specified below:", " Condiments: &condiments.", " Use 'ADDCONDIM and RMCONDIM TO %t' to add or remove condiments.", "And remember that you can @NOTEDIT the following properties:", " Refill & Evaporate: refill_msgs, evaporate_msgs, appear_msgs", " Consume: alreadyEmpty_msgs, oalreadyEmpty_msgs", " firstconsume_msgs, consume_msgs, lastconsume_msgs", " ofirstconsume_msgs, oconsume_msgs, olastconsume_msgs", " Descriptions: firstdescriptions_msgs, middescriptions_msgs, lastdescriptions_msgs", "In the messages you can use the following ampersand subs:", " &chunks, &full, &consumed, &condiments, &verb, &plural, &food, &condiment"} @prop #xxx."condiment_type" 1 rc @prop #xxx."condiments" {} rc @prop #xxx."condiment_msgs" "You &verb &condiment all over the &food." rc @prop #xxx."ocondiment_msgs" "%N &verbs &condiment all over %p &food." rc @prop #xxx."current_condiment" "butter" rc @prop #xxx."food_msg" "consumable" rc @prop #xxx."verb" "" r ;;#xxx.("icon") = "thing.gif" ;;#xxx.("banner") = "" ;;#xxx.("footer") = "" ;;#xxx.("web_alink_color") = "White" ;;#xxx.("external_stylesheet") = "encore_web_object.css" ;;#xxx.("underline_links") = 0 ;;#xxx.("aliases") = {"Generic Consumable", "gc"} ;;#xxx.("description") = "A consumable %t. Try a piece!" ;;#xxx.("object_size") = {22792, 1181453965} @verb #xxx:"description" this none this @program #xxx:description ChunksFromTop = this.maxChunks - this.chunks; if ((typeof(this.firstdescriptions_msgs) == STR) && (ChunksFromTop == 0)) ChunksLeftText = this:DoBoth(this.firstdescriptions_msgs); else if ((typeof(this.firstdescriptions_msgs) == LIST) && (ChunksFromTop < length(this.firstdescriptions_msgs))) ChunksLeftText = this.firstdescriptions_msgs[ChunksFromTop + 1]; ChunksLeftText = this:DoBoth(ChunksLeftText); else ChunksFromBottom = this.chunks; if ((typeof(this.lastdescriptions_msgs) == STR) && (ChunksFromBottom == 0)) ChunksLeftText = this:DoBoth(this.lastdescriptions_msgs); else if ((typeof(this.lastdescriptions_msgs) == LIST) && (ChunksFromBottom < length(this.lastdescriptions_msgs))) ChunksLeftText = this.lastdescriptions_msgs[ChunksFromBottom + 1]; ChunksLeftText = this:DoBoth(ChunksLeftText); else ChunksLeftText = this:send_message("middescriptions_msgs"); endif endif endif endif if (this.chunks > 1) Description = this:DoBoth(this.description); return {Description, ChunksLeftText}; else Description = " "; return {Description, ChunksLeftText}; "return ChunksLeftText"; endif "Last modified Sun Jun 10 00:32:47 2007 EDT by Max123 (#2362)."; . @verb #xxx:"consume" this none this @program #xxx:consume this.verb = verb; if ((this.location != player) && this.must_take) player:tell(this:send_message("notHolding_msg")); return; endif if (this.chunks == 0) this:send_messages("alreadyEmpty_msgs", "oalreadyEmpty_msgs"); return; endif chunks = 1; if (args && (tonum(args[1]) > 0)) chunks = tonum(args); if (chunks > this.chunks) chunks = this.chunks; endif endif if (this.auto_refill != 1) this.chunks = this.chunks - chunks; endif if (this.chunks == 0) this:send_messages("lastConsume_msgs", "olastConsume_msgs"); fork (this.returnDelay) this:goHome(); if (this.auto_refill == 2) if ($object_utils:isa(this.location, $room)) this.location:announce_all(this:send_message("refill_msgs")); endif this.chunks = this.maxChunks; endif endfork else if (this.chunks == (this.maxChunks - chunks)) this:send_messages("firstConsume_msgs", "ofirstConsume_msgs"); else this:send_messages("consume_msgs", "oconsume_msgs"); endif endif "Last modified Sun Jun 10 00:32:47 2007 EDT by Max123 (#2362)."; . @verb #xxx:"send_messages" this none this @program #xxx:send_messages "The syntax send_messages(message_property1,message_property2)"; "The first property goes to the player, the second to everyone else."; "If there are more than one possible message in the property, a random one is chosen. If both have more than one, the same line is chosen in each, if possible."; "If a message set is a list of messages, send_messages uses the same line number for each set."; this.save_line = -1; player:tell(this:send_message(args[1])); player.location:announce(this:send_message(args[2])); this.save_line = 0; "Last modified Sun Jun 10 00:32:47 2007 EDT by Max123 (#2362)."; . @verb #xxx:"goHome" this none this @program #xxx:goHome if ((typeof(this.home) == OBJ) && valid(this.home)) if (this.home != this.location) start = this.location; if (is_player(start)) start = start.location; endif if (this.home != start) this:moveto(this.home); if (this.location != this.home) this.owner:tell("Your ", this.name, " can't find its way home."); else end = this.location; if (is_player(end)) end = end.location; endif this.save_line = -1; if ($object_utils:isa(start, $room)) start:announce_all(this:send_message("evaporate_msgs")); endif if ($object_utils:isa(end, $room)) end:announce_all(this:send_message("appear_msgs")); endif this.save_line = 0; endif endif endif endif "Last modified Sun Jun 10 00:32:47 2007 EDT by Max123 (#2362)."; . @verb #xxx:"send_message" this none this @program #xxx:send_message "The syntax send_mesages(message_property1)"; "If there are more than one possible message in the property, a random one is chosen."; "If a message set is a list of messages, send_message uses the same line number for each set."; Message = args[1]; if (typeof(this.(Message)) == STR) text = this.(Message); this.save_line = 0; else if ((this.save_line > 0) && (this.save_line <= length(this.(Message)))) text_line = this.save_line; else text_line = random(length(this.(Message))); endif text = this.(Message)[text_line]; if (this.save_line != 0) this.save_line = text_line; endif endif AmpText = this:Amp_sub(text); ProText = $string_utils:pronoun_sub(AmpText); return ProText; "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"refill replace restore" this none none @program #xxx:refill if (player != this.owner) player:tell("Only the owner can refill."); else if (this.chunks == this.maxChunks) player:tell("It is already full."); else this.chunks = this.maxChunks; this.location:announce_all(this:send_message("refill_msgs")); endif endif "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"@look" this none none @program #xxx:@look for TextLine in (this.atlook_msg) AmpText = this:amp_sub(TextLine); ProText = $string_utils:pronoun_sub(AmpText); player:tell(ProText); endfor "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"Amp_sub" this none this @program #xxx:Amp_sub "Takes ampersand keywords and replaces them. Currently supported:"; "&chunks: number of chunks left."; "&consumed: number of chunks consumed from full."; "&full: number of chunks when full."; "&condiments: lists the legal condiments."; "&condiment: lists the current condiment in use."; "&food: the contents of 'food_msg'"; "&verb: the verb used to get here."; "&: an ampersand."; "&plural{string0,string1,...,stringmany}: return string corresponding to number of chunks left."; "&pluralc and &pluralf are for the number consumed and the number when full."; TheText = args[1]; if (this.condiment_type) Condiments = "any"; else length(this.condiments) ? Condiments = $string_utils:english_list(this.condiments) | (Condiments = "none"); endif length(this.current_condiment) ? Condiment = this.current_condiment | (Condiment = "nothing"); TheSubs = {{"&chunks", tostr(this.chunks)}, {"&consumed", tostr(this.maxChunks - this.chunks)}, {"&full", tostr(this.maxChunks)}, {"&condiments", Condiments}, {"&condiment", Condiment}, {"&verb", this.verb}, {"&food", this.food_msg}}; TheText = $string_utils:substitute(TheText, TheSubs); KeepGoing = 1; Text_End = length(TheText); PL = length("&plural"); Full = this.maxChunks + 1; Chunks = this.chunks + 1; while ((PluralLoc = index(TheText[1..Text_End], "&plural")) && KeepGoing) if (TheText[PluralLoc + PL] == "c") TheNumber = (Full - Chunks) + 1; TheLength = PL + 1; else if (TheText[PluralLoc + PL] == "f") TheNumber = Full; TheLength = PL + 1; else TheNumber = Chunks; TheLength = PL; endif endif if (TheText[PluralLoc + TheLength] == "{") if (PluralEnd = index(TheText[PluralLoc..Text_End], "}")) Plurality = TheText[(PluralLoc + TheLength) + 1..(PluralLoc + PluralEnd) - 2]; PluralList = $string_utils:explode(Plurality, ","); if (length(PluralList) > TheNumber) Plurality = PluralList[TheNumber]; else Plurality = PluralList[length(PluralList)]; endif TheText[PluralLoc..(PluralLoc + PluralEnd) - 1] = Plurality; else KeepGoing = 0; endif else Plurality = {"s", ""}[(TheNumber == 1) + 1]; TheText[PluralLoc..(PluralLoc + TheLength) - 1] = Plurality; endif Text_End = length(TheText); endwhile TheText = $string_utils:substitute(TheText, {{"&", "&"}}); return TheText; "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"DoBoth" this none this @program #xxx:DoBoth AmpText = this:Amp_sub(args[1]); ProText = $string_utils:pronoun_sub(AmpText); return ProText; "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"addcondim" any on this @program #xxx:addcondim "Check to make sure the condiment isn't already there."; Condiments = this.condiments; if (player == this.owner) if (dobjstr in Condiments) player:tell("There is already ", dobjstr, " in the condiments list: ", $string_utils:english_list(Condiments)); else Condiments = {@Condiments, dobjstr}; player:tell("You add ", dobjstr, " to the condiments around the ", this.name, "."); this.location:announce(player.name, " adds ", dobjstr, " to the condiments tray around the ", this.name, "."); this.condiments = Condiments; endif else player:tell("You need to ask ", this.owner.name, " for permission to add condiments to the tray around ", this.name, "."); endif "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"rmcondim" any from this @program #xxx:rmcondim if (player == this.owner) Condiments = this.condiments; if (Cond_Location = dobjstr in Condiments) Condiments = listdelete(Condiments, Cond_Location); player:tell("You remove ", dobjstr, " as a condiment for ", this.name, "."); this.condiments = Condiments; else player:tell("There is no ", dobjstr, " in the list of condiments for ", this.name, "."); (Condiments == {}) ? player:tell("In fact, ", this.name, " has no condiments.") | player:tell("Condiments: ", $string_utils:english_list(Condiments)); endif else player:tell("You'll have to ask ", this.owner.name, " to add ", dobjstr, "to the tray around ", this.name, "."); endif "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"add sprinkle spread put slather pour squeeze" any on this @program #xxx:add CondiType = this.condiment_type; Condiments = this.condiments; if ((Current_Condiment = CondiType) || (Current_Condiment = dobjstr in Condiments)) this.verb = verb; this.current_condiment = dobjstr; this.save_line = Current_Condiment; player:tell(this:send_message("condiment_msgs")); this.save_line = Current_Condiment; this.location:announce(this:send_message("ocondiment_msgs")); this.save_line = 0; this:consume(); else player:tell("There is no ", dobjstr, " for the ", this.name, "."); endif "Last modified Sun Jun 10 00:32:48 2007 EDT by Max123 (#2362)."; . @verb #xxx:"_html" this none this @program #xxx:_html {user, form} = args; base_url = tostr("http://", $network.site, ":", $network.webport, "/"); target = ""; title = this:titlec(); html = {}; "The following lines are magic! Why does putting these lines here force Xpress to include the whole header?!?!"; "==="; message1 = {""}; message1 = {@message1, tostr(" ")}; frame_title = {tostr(" ", title, " (", $network.MOO_name, ")")}; message1 = $list_utils:append(message1, frame_title); html = message1; "==="; title = tostr("
", this:title(0), "
"); "======= Insert back link ======"; buttons = {tostr("", $encore_web_utils:get_icon(user, $xpress_client, "back.gif", "Go Back/View Previous"), "", "

")}; "==============================="; html = {@html, title}; html = $list_utils:append(html, buttons); _html_ = {}; _line_ = " "; _html_ = {@_html_, _line_}; _html_ = {@_html_, "

"}; _line_ = ""; _line_ = _line_ + " "; stuff = this:description(); _html_ = {@_html_, _line_}; _line_ = ""; _line_ = _line_ + " "; _line_ = _line_ + stuff[1]; _line_ = _line_ + " "; _html_ = {@_html_, _line_}; _html_ = {@_html_, "
"}; _line_ = ""; _line_ = _line_ + " "; _line_ = _line_ + stuff[2]; _line_ = _line_ + " "; _html_ = {@_html_, _line_}; _html_ = {@_html_, "

"}; html = $list_utils:append(html, _html_); return html; . =============== Generic Edible @create #xxx named Generic Edible:Generic Edible,ge ;;#xxy.("aliases") = {"Generic Edible", "ge"} ;;#xxy.("description") = "An edible %t. Try a piece!" @verb #xxy:"eat bite nibble" this none none @program #xxy:eat this:consume(); "Last modified Wed Apr 14 10:51:06 1999 by Max (#147)."; . ================ Generic Drinkable @create #xxx named Generic Drinkable:Generic Drinkable,gd ;;#xxz.("aliases") = {"Generic Drinkable", "gd"} ;;#xxz.("description") = "A drinkable %t. Try a swig!" @verb #xxz:"drink sip" this none none rxd @program #xxz:drink this:consume(); "Last modified Wed Apr 14 10:53:21 1999 by Max (#147)."; .