Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Making Meals: How to make prepared meal items from a reaction.  (Read 3563 times)

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile

This requires DFHack!

Making prepared meals from a reaction has been a long requested feature, and I have finally figured out a way to do it.

The following DFHack script, when used with proper reactions, will allow you to make any prepared meal items you want.

First a few notes:
  • AFAIK if you provide an invalid "LEVEL" for a food item it will not be possible to make it with the hardcoded cooking reaction, but it still works with this script.
  • You will need to register your reactions in the script, see the comments at the end of the script for details.
  • This script is not a command! You can call it like a command, but you should only do so once when the world is loaded.
  • If you want to see this in action download Rubble and look at the "User/DFHack/Cook Steak" addon.
  • I identified two previously unknown offsets in the ingredient type, each is commented in the script.

Code: [Select]
local eventful = require "plugins.eventful"

-- This Lua hook will make a prepared meal using the items with reagent IDs "item_1", "item_2",
-- "item_3", and "item_4" as the first, second, third, and fourth meal ingredients.
--
-- Ingredient reagents (the ones with the special IDs) will always have the full stack used up.
--
-- The number of ingredients does NOT have to match the food item level!
--
-- The meal type is determined by the the reaction name. The reaction must be named "<Reaction ID>|<Food ID>",
-- for example "COOK_MEAL|ITEM_FOOD_ROAST"
--
-- Here are some example reactions.
--
-- # Make a roast from any meat (but you only need two ingredients!)
-- [REACTION:COOK_MEAL|ITEM_FOOD_ROAST]
-- [NAME:cook a roast]
-- [BUILDING:KITCHEN:NONE]
-- [REAGENT:item_1:1:MEAT:NONE:NONE:NONE]
-- [REAGENT:item_2:1:MEAT:NONE:NONE:NONE]
-- [PRODUCT:0:0:ROCK:NONE:INORGANIC:NONE]
-- [SKILL:COOK]
--
-- # You need a ITEM_FOOD_PIE item defined and flour materials must have the FLOUR_MAT
-- # reaction class for this reaction.
-- [REACTION:COOK_MEAL|ITEM_FOOD_PIE]
-- [NAME:cook a fruit pie (flour and fruit)]
-- [BUILDING:KITCHEN:NONE]
-- [REAGENT:item_1:1:POWDER_MISC:NONE:NONE:NONE]
-- [REACTION_CLASS:FLOUR_MAT]
-- [REAGENT:bag:1:NONE:NONE:NONE:NONE]
-- [CONTAINS:item_1]
-- [PRESERVE_REAGENT]
-- [DOES_NOT_DETERMINE_PRODUCT_AMOUNT]
-- [REAGENT:item_2:1:PLANT_GROWTH:NONE:NONE:NONE]
-- [PRODUCT:0:0:ROCK:NONE:INORGANIC:NONE]
-- [SKILL:COOK]
--
function cookMeal(reaction, reaction_product, unit, in_items, in_reag, out_items, call_native)
call_native.value = false
local ingredients = {}
local amount = {}

-- We do a bit of trickery here to make the reaction always use the whole stack.
for x = 0, #in_items - 1, 1 do
if in_reag[x].code == "item_1" then
ingredients[1] = in_items[x]
amount[1] = in_items[x].stack_size
in_items[x].stack_size = in_reag[x].quantity
elseif in_reag[x].code == "item_2" then
ingredients[2] = in_items[x]
amount[2] = in_items[x].stack_size
in_items[x].stack_size = in_reag[x].quantity
elseif in_reag[x].code == "item_3" then
ingredients[3] = in_items[x]
amount[3] = in_items[x].stack_size
in_items[x].stack_size = in_reag[x].quantity
elseif in_reag[x].code == "item_4" then
ingredients[4] = in_items[x]
amount[4] = in_items[x].stack_size
in_items[x].stack_size = in_reag[x].quantity
end
end

local ok = true

if ingredients[1] == nil then
ok = false
end
if ingredients[2] ~= nil then
if not ok then
error "Ingredient missing from sequence: 1"
end
else
ok = false
end
if ingredients[3] ~= nil then
if not ok then
error "Ingredient missing from sequence: 2"
end
else
ok = false
end
if ingredients[4] ~= nil then
if not ok then
error "Ingredient missing from sequence: 3"
end
else
ok = false
end

local mealtype = dfhack.items.findSubtype("FOOD:"..string.match(reaction.code, "[a-zA-Z_]+|([a-zA-Z_]+)"))
if mealtype == -1 then
error "Invalid FOOD type."
end

local item = df['item_foodst']:new()

item.id = df.global.item_next_id
df.global.world.items.all:insert('#',item)
df.global.item_next_id = df.global.item_next_id + 1


item:setSubtype(mealtype)

-- These always seem to be -1.
item.entity = -1
item.recipe_id = -1

local stacksize = 0
for i, ingredient in ipairs(ingredients) do
local imat = dfhack.matinfo.decode(ingredient)
stacksize = stacksize + amount[i]
item.ingredients:insert('#', {
new = true,

-- Seems to always be 0.
anon_1 = 0,

-- The ingredient item type.
item_type = ingredient:getType(),

-- Seems to always be -1.
unk_4 = -1,

-- Ingredient material type and index.
mat_type = imat.type,
mat_index = imat.index,

-- The creator unit ID.
maker = unit.id,

-- The ingredient quality.
unk_10 = 0,

-- The skill level of the maker.
unk_14 = 0,

-- Seems to always be -1.
unk_18 = -1,
})
end

item.stack_size = stacksize

-- This is something of a hack to assign ingredient quality,
-- we just calculate item quality once for each ingredient, then
-- set ingredient quality directly from item quality.
for _, ingredient in ipairs(item.ingredients) do
item:assignQuality(unit, df.job_skill["COOK"])
ingredient.unk_10 = item.quality
end

-- Set item quality for one last time.
item:assignQuality(unit, df.job_skill["COOK"])

item:setMakerRace(df.global.ui.race_id)
item:setMaker(unit.id)

item:categorize(true)
out_items:insert('#', item)
end

-- You will need to register your reactions here, just like this example.
eventful.registerReaction("COOK_MEAL|ITEM_FOOD_STEAK", cookMeal)

Here is the example reaction and food item:

Code: [Select]
[REACTION:COOK_MEAL|ITEM_FOOD_STEAK]
[NAME:cook a steak]
[BUILDING:KITCHEN:NONE]
[REAGENT:item_1:1:MEAT:NONE:NONE:NONE]
[PRODUCT:0:0:ROCK:NONE:INORGANIC:NONE]
[SKILL:COOK]

[ITEM_FOOD:ITEM_FOOD_STEAK]
[NAME:steak]
[LEVEL:1]
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS

Klisz

  • Bay Watcher
  • Dabbling Modder
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #1 on: May 04, 2015, 01:45:31 pm »

Ooh, nice. PTW.
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #2 on: May 04, 2015, 11:15:15 pm »

...Huh. Was this requested? IIRC, the SCP mod has had SCP-458 for a while, which very successfully makes a prepared meal (pizza) made out of the person who does the reaction's favorite ingredients.

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #3 on: May 07, 2015, 07:50:38 am »

Ah, good to know.

Anyway the script I provided is generic and easy to use, so other (non-dfhack literate) modders can hopefuly use it to make some nice stuff.
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #4 on: May 08, 2015, 01:34:14 am »

...Huh. Was this requested? IIRC, the SCP mod has had SCP-458 for a while, which very successfully makes a prepared meal (pizza) made out of the person who does the reaction's favorite ingredients.
lol, what? Custom prepared meals are super awesome for Total Conversions, for example a race that eats metal or rock...
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #5 on: May 08, 2015, 01:45:14 am »

I always dealt with that by just giving the rocks [EDIBLE_COOKED]...

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #6 on: May 08, 2015, 12:21:05 pm »

That works on inorganics? I remember that rotting and miasma etc only works on specific item types, didnt knew that civs would accept boulders as ingredients for their prepared meals.
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #7 on: May 08, 2015, 01:35:06 pm »

And then using a custom reaction to turn them into a MEAT item, sorry. Goddamn, I keep forgetting steps lately.

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #8 on: May 16, 2015, 11:38:20 am »

More interesting (for my purposes anyway) was the ability to make meals that could not be used with the hardcoded reactions. That way things like the "bake bread" reactions some people like to add can produce a "bread" meal instead of a plant or meat item.

Anyway, this has served it's primary purpose, it filled an afternoon with delightful DFHacking :)
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #9 on: May 16, 2015, 11:55:05 am »

Yep, one could write an entire extended cooking mod with this.
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #10 on: May 16, 2015, 11:59:48 am »

Oh, I plan to, someday... But I have other more interesting projects going right now, so probably not for a while :)
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS

Button

  • Bay Watcher
  • Plants Specialist
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #11 on: May 19, 2015, 12:06:34 pm »

PTW
Logged
I used to work on Modest Mod and Plant Fixes.

Always assume I'm not seriously back

Iä! RIAKTOR!

  • Bay Watcher
    • View Profile
Re: Making Meals: How to make prepared meal items from a reaction.
« Reply #12 on: December 30, 2020, 02:39:37 pm »

I tested some, that makes bread impossible. If FOOD items have no solid ingredient, game crashes.
Logged