Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: require water for booze?  (Read 1894 times)

Quarque

  • Bay Watcher
    • View Profile
require water for booze?
« on: June 10, 2022, 10:33:04 am »

I would like to modify the brew reaction, such that you need water first.

The reactions seems to work, but getting the dwarves to fill empty buckets with water is awkward.
I have built a well and designated a flat area as a pond. Then you can cancel the pond when a dwarf has filled a bucket. But is there any better way to do this? Perhaps by adding another reaction?

And can the reactions for booze be improved? What I have now is:
Spoiler (click to show/hide)
Logged

FantasticDorf

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #1 on: June 10, 2022, 11:17:24 am »

A aged reply is that it could be possible by use of a script, but you'd have to make the solution yourself.

People prior to you have suggested a [NEEDS_WATER] function similar to [NEEDS_MAGMA] that works like the mentioned with the inaccessible tile, but the hermit "handpump" mentioned and the code provided is a startpoint to getting to grips with what you may need to do. In addition, if you set something up, it would be possible to assign this to a custom token in the latest DFhack.

So in essence, every time the desired directional space runs the reaction, it'd pull up water, then you could generate a water-bucket at the end of the reaction. The DFhack steam engine that's included with every release may use something similar as my own hint.
Logged

Quarque

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #2 on: June 11, 2022, 07:35:09 am »

Thanks for the pointer. So a better idea is to leave the reactions in the raws unchanged and use a script. With the eventful module it should be possible to alter the brew reactions:

  • check if there is water nearby the still
  • remove a unit of water if there is
  • if there is no water, cancel the job with a warning

Another relevant old post contains a script that almost does what I need: http://www.bay12forums.com/smf/index.php?topic=141497.15
But this post is from 2014 and some functions/data structures used by this script have changed.
I almost got it to work, but not quite:

Spoiler (click to show/hide)

The problem is that the seventh argument (call_native) is never passed on. In DFHack I get an error message that I am trying to write to a nil value.

I found another post from 2017 where someone else has the same problem:

I hate Fortress Mode modding  :'(
Me too. The raws modding too :P.

Can you print all the args to lua? I.e.
Code: [Select]
function reaction() local args={...}; printall(args); end
Oh derp I didn't think to do that when trying to work stuff out.
It only receives 6 args, where the 7th should be the call_native: 1 is a reaction, 2 is a reaction product item table, 3 is a unit, 4 is a table of items, 5 is a table of reaction reagents, 6 is a table of items.

Maybe it's something related to the reaction using a custom building? That's the only thing I could think of that deviates slightly from the norm.

I suspect this is a bug in the eventful module of dfhack that was introduced, somewhere between 2014 and 2017 the function was changed. Originally it only took 6 parameters; the second parameter (reaction_product) is new. It isn't present in the old scripts from 2014 and if you look at the documentation of https://docs.dfhack.org/en/stable/docs/Lua%20API.html?highlight=eventful#eventful, you see the parameter mentioned in the description of onReactionComplete, but it is missing in the example code.

Am I missing something? Can I report bugs in DFHack somewhere? And is there another way to cancel the reaction? I tried reaction_product.probability = 0, but that had no effect.
Logged

FantasticDorf

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #3 on: June 11, 2022, 09:40:13 am »

Am I missing something? Can I report bugs in DFHack somewhere? And is there another way to cancel the reaction? I tried reaction_product.probability = 0, but that had no effect.

Ill PM you a discord link to the DFhack hub, elsewise like most of us its merely waiting around for inspiration to strike or someone to dive in and finish the last piece of the puzzle out of their own initative.

Probability doesn't physically turn it off, it just executes it with no chance of procuring the *product, as a alternative you could have it be probability 0 then return the water if false to where it came from, assuming it the same water that got drawn up (perhaps into a 1x1 solid cavity in the workshop to "hold" the water, but im unsure if the dynamics of having that much water nearby would make it deconstruct.)
« Last Edit: June 11, 2022, 10:02:30 am by FantasticDorf »
Logged

Quarque

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #4 on: June 11, 2022, 11:34:44 am »

Thanks, I will see if I can get some help on discord.

To be clear, all I've tried so far is to modify the brew reactions. I haven't tried yet to add a check when building the still.

I reported the issue with the registerReaction function on the DFHack issue tracker. The folks there have already confirmed it as a bug and they're working on it. 8)
Logged

Quarque

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #5 on: June 14, 2022, 06:23:21 pm »

This script makes brewing use one unit of clean water.

Place the still adjacent to clean water, such as a river, pool or channel.
Water that is salt or stagnant will be ignored.
The water has to be accessible. A grate on top works, a floor on top doesn't.

Making mead will not require water. Honey is already a liquid. ;)

The script does not work with old versions of DFHack.
It needs version 0.47.05-r6 or newer.

Spoiler (click to show/hide)
« Last Edit: June 19, 2022, 08:59:47 am by Quarque »
Logged

brewer bob

  • Bay Watcher
  • euphoric due to inebriation
    • View Profile
Re: require water for booze?
« Reply #6 on: June 20, 2022, 06:55:21 am »

Looks interesting...

This script makes brewing use one unit of clean water.

Place the still adjacent to clean water, such as a river, pool or channel.
Water that is salt or stagnant will be ignored.
The water has to be accessible. A grate on top works, a floor on top doesn't.

If salt water can be ignored, could the script be changed so that salt contaminated water is needed instead of clean water? Been thinking of modding in salterns as a custom building for salt production, but the best idea so far was to do a modified version of an "empty bucket" reaction which has a chance of giving salt.

(I have no idea about scripting or what's possible or not, so sorry if this is a dumb question.)

Quarque

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #7 on: June 20, 2022, 11:05:58 am »

(I have no idea about scripting or what's possible or not, so sorry if this is a dumb question.)
No man, no apology needed at all. The learning curve for writing DFHack scripts is a cliff, I spent days cursing my computer before I got it right (and only thanks to people on Discord helping out).

Anyway, yes, you can change the script so that brewing requires salt water. The part of the script that controls the accepted fluids is these lines:

Code: [Select]
      blockDesignation.flow_size > 0 and
      blockDesignation.liquid_type == intToBool(df.tile_liquid.Water) and
      not blockDesignation.water_stagnant and
      not blockDesignation.water_salt

The 4th line checks for salt. To make brewing accept only salt water, change it to:

Code: [Select]
      blockDesignation.flow_size > 0 and
      blockDesignation.liquid_type == intToBool(df.tile_liquid.Water) and
      not blockDesignation.water_stagnant and
      blockDesignation.water_salt

I would recommend also changing the error message from:
Code: [Select]
   dfhack.gui.showZoomAnnouncement(df.announcement_type.CANCEL_JOB, unit.pos, dfhack.TranslateName(unit.name).." cancels "..reaction.name..": Needs clean water." , COLOR_RED, true)
to:
Code: [Select]
   dfhack.gui.showZoomAnnouncement(df.announcement_type.CANCEL_JOB, unit.pos, dfhack.TranslateName(unit.name).." cancels "..reaction.name..": Needs salt water." , COLOR_RED, true)
If you want to be thorough, you could also change the help text to match.

I've been toying with the idea to allow brewing from magma in case there is only magma available and no water.. someone on discord suggested that it could yield liquid fire. Any ideas welcome. ;)
« Last Edit: June 20, 2022, 11:14:03 am by Quarque »
Logged

Quarque

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #8 on: June 20, 2022, 11:30:28 am »

P.S.: reading your post again, I see you don't want to brew booze from salt water, but you want to produce salt from salt water.

That's more difficult, but it should be possible. You would need to add a custom reaction to the raws that produces water from salt, and couple the script to your custom reaction. To do this, replace this code:

Code: [Select]
         if string.startswith(reaction.code,'BREW_DRINK') then
            eventful.registerReaction(reaction.code,usewater)
         end

with something like
Code: [Select]
         if reaction.code == 'YOUR_SALTERN_REACTION') then
            eventful.registerReaction(reaction.code,usewater)
         end

In addition, you can simplify the script further. I had to work around the problem that the callback function (usewater) is invoked once for each reaction product. Brewing has two products (drink and seeds) and you have to prevent the callback function from consuming water twice, or throwing two error messages. That is why I needed to add:

Code: [Select]
   -- The reaction calls this function once for each product.
   --  call 1: produce drink
   --  call 2: produce seeds
   -- We only want to check for water the first time.
   if reaction_product.item_type ~= df.item_type.DRINK then
      call_native.value = waterFound
      return
   end
But you would probably not need that.

The more difficult part is how to add your custom reaction to a workshop. It should be possible, but I don't know how. Hopefully someone else can help you there. You could also overwrite an existing reaction like `make mead` as a workaround.
« Last Edit: June 20, 2022, 11:33:01 am by Quarque »
Logged

FantasticDorf

  • Bay Watcher
    • View Profile
Re: require water for booze?
« Reply #9 on: June 20, 2022, 11:46:07 am »

Salt has its own hardcoded material token, so its relatively straightfoward to set up, i wonder what bob has in mind for it.

Alternatively for instance, by following a variant of the process you've already described for saltwater, you could "extract" stagnant water and then generate *actual filth, mud, and other conspicous things.
Logged

brewer bob

  • Bay Watcher
  • euphoric due to inebriation
    • View Profile
Re: require water for booze?
« Reply #10 on: June 20, 2022, 02:13:47 pm »

Thanks! Good to know it'd be technically possible (and I even understood the explanations).

Making the 'water to salt' reaction isn't in itself a problem, though I guess in reagents you can't use contaminants (or that's how I've understood)? Which won't be a problem if the building itself just checks if there's salt water next/near to it, so I could just leave the water reagent away.

Anyway, it'll take time before I'll try to test the saltern script. Better finish other modding stuff first before trying something which I'll have to spend much time learning.

Salt has its own hardcoded material token, so its relatively straightfoward to set up, i wonder what bob has in mind for it.

Just working on a personal mod (which has sort of gotten out of hand) with all sorts of medieval industries, of which making salt is one. I don't have much use for the salt yet, except for a salting meat prototype.

you could "extract" stagnant water and then generate *actual filth, mud, and other conspicous things.

Haha, I've actually thought about what'd be a good way to have dwarves produce, err, "yellow filth", as it'd be great to have it in wool-working reactions (like, fulling in a tub filled ankle-deep with said "filth")