Template: VESSEL - ThePix/QuestJS GitHub Wiki

This is about how to handle liquids, but can also be used for powders like salt or sand, so the term "fluid" is generally used in the code. It is fairly basic system that assumes a vessel is either full or empty and all vessels are the same volume. It does not allow for mixing of liquids either. It would certainly be possible to extend it, if required, but you should think carefully if the complexity is worth it.

A "fluid" comes from a "source", can be placed in a "vessel", potentially transferred to another, and finally disposed of in a "sink". Thus there are four components to consider.

Fluids

Fluids are easy; they are set up in settings.js by assigning an array of names:

settings.fluids = ['water', 'honey', 'lemonade']

Sources

A source is potentially anything with a "isSourceOf" function attribute. That can be a location or an item. The function should accept a string, and return true if the string matches the liquid it provides.

createItem("kitchen_sink", {
  loc:"kitchen",
  scenery:true, 
  examine:"A dirty sink.",
  isSourceOf:function(fluid) {
    return fluid === "water" 
  },
})

That is pretty much it. As it is a function, you can have the return value depend on some other value. This example will only provide water once the old pipe is fixed.

  isSourceOf:function(fluid) {
    return w.old_pipe.fixed && fluid === "water" 
  },

Vessels

To make a vessel, just give the item the VESSEL template. Chances are you want to give it the TAKEABLE template too.

createItem("jug", TAKEABLE(), VESSEL(), {
  loc:"big_kitchen_table",
  examine:"A small jug, striped blue and white.",
})

The "containedFluidName" attribute will contain the name of the liquid when the vessel is full.

If the vessel has an "afterFill" function, this will fire when the item is filled. Similarly, if it has an "afterEmpty" function that will fire when it is emptied (after the sink function discussed later has fired). You can also add "testFill" and "testEmpty" attributes to restrict either action. These are discussed in more detail here.

Sinks

A sink is any item or location with a "sink" function attribute. The sink attribute will be given the fluid name, the character doing it, and the vessel object. It can do with it whatever it likes with that - as long as it prints a message.

createItem("kitchen_sink", {
  loc:"kitchen",
  scenery:true, 
  examine:"A dirty sink.",
  isSourceOf:function(fluid) {
    return fluid === "water" 
  },
  sink:function(fluid, char, vessel) {
    msg("{nv:char:empty:true} {nm:item:the} into the dirty sink.", {char:char, item:vessel} )
  },
})

Game considerations

There is a lot of potential for a user to use liquids in unexpected ways. What happens if oil or water is poured onto anything on fire? I would advise providing an infinite supply of any liquids to ensure the player cannot get stuck after emptying the liquid into the wrong place - this system will let the player empty a vessel anywhere!

You might want to think about containers... Why can the box not get used to hold a liquid? Or can it?