Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Connecting lua scripts to reactions + related worldgen questions  (Read 3153 times)

LilyInTheWater

  • Bay Watcher
  • Me want bite. Me want plant corn dog delight.
    • View Profile

I've been working on a gem people race who reproduce exclusively through taking large gems and turning them into gem people. I know this needs a lua script to do this (specifically the create-unit modding script in dfhack, but I got the script writing for that figured out.). I have several questions.

-When writing up the reaction, what do I need to write in the product to make it run the script? I already have the reagent and workshop specified. I tried to look at an example reaction that uses a script but I couldn't find the part where the reaction said "use x script" which is what I need.

-Do I actually need to write anything in the product for this reaction? Products have always kind of tripped me up when writing reactions, so any help is appreciated. If so, what?

-How do I connect the reaction to the script?

-Is there any known worldgen weirdness involving races that exclusively use reactions to reproduce? Including ones that need the create-unit lua script like above?
Logged
Whatchu gonna do when I'm fucking small
Like one inch tall
You won't see me coming at all

He or They pronouns

FantasticDorf

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #1 on: January 06, 2021, 04:10:57 pm »

Given your content, whether it still works needs to be seen but "construct-creature.lua by IndigoPhoenix" might fit your purposes because of the way it transfers the reagent material directly into it.  Im new to writing in DFhack too, but the workshop reactions are fufilled by inputting them (somewhere, anywhere) onto the dfhack.init file in a particular code string to execute when the game is loaded, usually referencing a seperate .lua with the code in it.

I like to use grown.lua (which i picked up as part of a older modification's dfhack spec) which applies a simple grown flag to the output which is useful for elf modifications. etc like a so. My particular example is to process cut logs, then restore them to be grown via elven means of... tree necromancy? Its nonspecific but it ought to work in a way that i can simply launder my logs through the shrine and then not alienate any traders later so long as im careful.

Location, then reaction-product-trigger (pretty typical if you've got DFhack of the latest version out the box, its simply referencing the scope from the DFfilefolder's position, and would change if you added another dfhack.init somewhere else) input a name from the reaction file, then the command references the actual code to apply in square brackets so it works.

The // is just a comment to keep track of what its meant to be doing and anything past // doesnt count as the code will stop reading.

Code: [Select]
modtools/reaction-product-trigger -reactionName DENDROMANTIC_REVIVAL -command [ grownwood.lua \\OUTPUT_ITEMS ]
Feel free to correct me anybody if i've actually got it wrong myself. Its all a opportunity to learn. Notepad++ application is probably the easiest way to open them to look inside any .lua file and also make relevant edits.

I do kind of want to make procedural wood ents now though. Thinking of the hideously strong dryads/ents i could make with custom trees, there's more than enough old abandoncode elf mods to finish it.
Logged

Atkana

  • Bay Watcher
  • [CURIOUSBEAST]
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #2 on: January 07, 2021, 03:48:43 am »

1) When writing up the reaction, what do I need to write in the product to make it run the script? I already have the reagent and workshop specified. I tried to look at an example reaction that uses a script but I couldn't find the part where the reaction said "use x script" which is what I need.
2) Do I actually need to write anything in the product for this reaction? Products have always kind of tripped me up when writing reactions, so any help is appreciated. If so, what?
3) How do I connect the reaction to the script?
4) Is there any known worldgen weirdness involving races that exclusively use reactions to reproduce? Including ones that need the create-unit lua script like above?

1) You don't have to write anything special in the reaction itself (see later points). I think there was/still is functionality to do it by naming reactions in certain ways, but I don't know if anyone still does that.
2) IIRC yes, the reaction needs a product, or else the code doesn't actually trigger (even though the documentation says otherwise). There's supposed to be a way to prevent the product from actually being made, but I believe that functionality is broken/removed (though I could be misremembering, it's been ages), so most people set the product to be a boulder of a dummy material that turns into gas instantly.
3) By using modtools/reaction-trigger. You should include each command inside an onLoad init file, so they get automatically run every time a world is loaded (otherwise you'd have to manually type in each command into the console every time you load up the world :P).
Here's an example from an old mod I abandoned. When the reaction with the ID "THE_HIVE_SPAWN_QUEEN" is completed, a QUEEN caste of the creature THE_HIVE is spawned that's part of the fort, and uses THE_HIVE entity's naming conventions:
Code: [Select]
modtools/reaction-trigger -reactionName THE_HIVE_SPAWN_QUEEN -command [ modtools/create-unit -race THE_HIVE -caste QUEEN -setUnitToFort -name THE_HIVE -location [ \\LOCATION ] -age 0 ]

4) If I remember correctly, there will be problems in worldgen for creatures that reproduce solely from reactions. create-unit combined with reaction-trigger only spawns the creatures from their reactions when the reaction is used during fortress mode. This means that for all of worldgen, no new creatures are actually spawned, and so that civilisation is left with just their default level of population that the game initially spawns them with (assuming they can't reproduce on their own).

It might be possible to rig something up to have them create more of themselves during worldgen, like say giving them a dummy item that they can create as a craft, and then periodically replacing any of those items stored in a site with people instead. It'd obviously need a custom made script for it (I don't think one such script exists currently), and I'm not sure how possible it is, since I've never touched anything worldgen related before. 🤔

Given your content, whether it still works needs to be seen but "construct-creature.lua by IndigoPhoenix" might fit your purposes because of the way it transfers the reagent material directly into it.
That does look pretty old, and I'm not sure how well it'll work, but I'm glad I stumbled upon it. I never realised/considered you could just straight-up edit the materials a creature is made up from. I was considering potentially picking up one of my old mod concepts that involves creating golems, and I was going to just cheat making them out of a particular material by colouring their body material based on the colour of the material used, but actually making them out of their material sounds better.

Though actually looking into it, it doesn't look like those changes to a unit's materials are actually saved, so you'd have to reapply them whenever they're loaded, which seems like potentially more effort than it's worth.

FantasticDorf

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #3 on: January 07, 2021, 04:00:38 am »

That does look pretty old, and I'm not sure how well it'll work, but I'm glad I stumbled upon it. I never realised/considered you could just straight-up edit the materials a creature is made up from. I was considering potentially picking up one of my old mod concepts that involves creating golems, and I was going to just cheat making them out of a particular material by colouring their body material based on the colour of the material used, but actually making them out of their material sounds better.

Though actually looking into it, it doesn't look like those changes to a unit's materials are actually saved, so you'd have to reapply them whenever they're loaded, which seems like potentially more effort than it's worth.

I would figure that figuratively if the creature is already made of wood or some sort of gem material and defined under a [DOES_NOT_EXIST] (which does allow interaction summoning if to take a alternative route to 'createcreature') and a subtype of material, it would keep the consistency and hopefully the installed subtype of material used from the reaction, though having your Uber Precious Gemstone person/mega-rare wood Ent suddenly become brittle between saves would suck, they wouldnt cease to exist or fall apart because they have become essentially ethereal with a lack of material all over the body.

Though i havent in practice had time to try much dfhacking because im so busy building and learning on the side. Is Onload.init safer broadly than putting it in dfhack.init in the main file to do the same thing? Though i wish it could tailor scripts to a specific world rather than risk porting and having it break or become confused.

4) If I remember correctly, there will be problems in worldgen for creatures that reproduce solely from reactions. create-unit combined with reaction-trigger only spawns the creatures from their reactions when the reaction is used during fortress mode. This means that for all of worldgen, no new creatures are actually spawned, and so that civilisation is left with just their default level of population that the game initially spawns them with (assuming they can't reproduce on their own).

Players can self resolve this by simply doing some raiding activities (I mean you have populations who can be constructed on spot, why not?) to conquer new non-historical populations and setting the initial populations high, to give more fodder though its not a proper uptick without them, with a quickly conquered pits yielding ideal goblin fodder soldiers while the fortress deals with the main civilization occupants.

Unless they were to count each weekly cycle as a flat +1 per settlement/larger market activated settlement a year meaning 52(.1429 rounded down anyway makes 52) new members of that workshop-product species a year but that sounds maybe a little bit intensive. Backlog of 300 years of dwarven golem making of 15 different varieties meaning 780 new immortal no-emotion members per year (234000 total) definitely seems like something you want to have a toggle of if maybe also for balance reasoning if player fortress options are more extensive than what was envisioned for worldgen.
« Last Edit: January 07, 2021, 04:23:12 am by FantasticDorf »
Logged

Atkana

  • Bay Watcher
  • [CURIOUSBEAST]
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #4 on: January 08, 2021, 06:05:55 am »

I would figure that figuratively if the creature is already made of wood or some sort of gem material and defined under a [DOES_NOT_EXIST] (which does allow interaction summoning if to take a alternative route to 'createcreature') and a subtype of material, it would keep the consistency and hopefully the installed subtype of material used from the reaction, though having your Uber Precious Gemstone person/mega-rare wood Ent suddenly become brittle between saves would suck, they wouldnt cease to exist or fall apart because they have become essentially ethereal with a lack of material all over the body.
[DOES_NOT_EXIST] just prevents a creature from naturally appearing in the game (I believe). It doesn't actually stop the creature from existing - their data (including their materials) are all loaded up as usual, which is why they can be summoned just fine in the game. Because they're just boring normal creatures, the same thing about material changes reverting still applies sadly :c

Also trying to change out the materials used in the creature's tissues to a pre-defined material (like iron) instead of a creature-defined one doesn't change this. I think the body plan bit that you can edit actually outlines what materials are used for the tissues.

Though i havent in practice had time to try much dfhacking because im so busy building and learning on the side. Is Onload.init safer broadly than putting it in dfhack.init in the main file to do the same thing? Though i wish it could tailor scripts to a specific world rather than risk porting and having it break or become confused.
The commands in dfhack*.init files are run once when the game is loaded. The commands in onLoad*.init files on the other hand, are run whenever a world is loaded. It's an important distinction because some utilities (such as modtools/reaction-trigger) will wipe anything they have registered whenever a world is unloaded. This is because things like whole setups about what mods are running can be entirely different between different save files and their raws. If you want to interact with such scripts, you need to use an onLoad*.init file, because if the commands were in a dfhack*.init file they'd only work up until you save a world in that session (or not at all, in cases where the scripts check to ensure a world is currently loaded when they're run).

Also, onLoad*.init files can be placed inside the raw or raw/objects folders, and so can have different sets of commands on a per-world basis, if that's what you were after.

FantasticDorf

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #5 on: January 08, 2021, 06:17:52 am »

The commands in dfhack*.init files are run once when the game is loaded. The commands in onLoad*.init files on the other hand, are run whenever a world is loaded. It's an important distinction because some utilities (such as modtools/reaction-trigger) will wipe anything they have registered whenever a world is unloaded. ~snip~ :If you want to interact with such scripts, you need to use an onLoad*.init file, because if the commands were in a dfhack*.init file they'd only work up until you save a world in that session (or not at all, in cases where the scripts check to ensure a world is currently loaded when they're run).

Also, onLoad*.init files can be placed inside the raw or raw/objects folders, and so can have different sets of commands on a per-world basis, if that's what you were after.

Aheheh, yeah, i found this out the hard way recently when my targeted lua fell apart, and also thats really neat & explains a few things for me why i found some mysterious luas in a old Teneb modification i was tinkering with. They must have extracted it from a save and left it behind so huh, that's good to know.
Logged

LilyInTheWater

  • Bay Watcher
  • Me want bite. Me want plant corn dog delight.
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #6 on: January 09, 2021, 12:23:04 am »


1) You don't have to write anything special in the reaction itself (see later points). I think there was/still is functionality to do it by naming reactions in certain ways, but I don't know if anyone still does that.

2) IIRC yes, the reaction needs a product, or else the code doesn't actually trigger (even though the documentation says otherwise). There's supposed to be a way to prevent the product from actually being made, but I believe that functionality is broken/removed (though I could be misremembering, it's been ages), so most people set the product to be a boulder of a dummy material that turns into gas instantly.

3) By using modtools/reaction-trigger. You should include each command inside an onLoad init file, so they get automatically run every time a world is loaded (otherwise you'd have to manually type in each command into the console every time you load up the world :P).
Here's an example from an old mod I abandoned. When the reaction with the ID "THE_HIVE_SPAWN_QUEEN" is completed, a QUEEN caste of the creature THE_HIVE is spawned that's part of the fort, and uses THE_HIVE entity's naming conventions:
Code: [Select]
modtools/reaction-trigger -reactionName THE_HIVE_SPAWN_QUEEN -command [ modtools/create-unit -race THE_HIVE -caste QUEEN -setUnitToFort -name THE_HIVE -location [ \\LOCATION ] -age 0 ]

4) If I remember correctly, there will be problems in worldgen for creatures that reproduce solely from reactions. create-unit combined with reaction-trigger only spawns the creatures from their reactions when the reaction is used during fortress mode. This means that for all of worldgen, no new creatures are actually spawned, and so that civilisation is left with just their default level of population that the game initially spawns them with (assuming they can't reproduce on their own).

It might be possible to rig something up to have them create more of themselves during worldgen, like say giving them a dummy item that they can create as a craft, and then periodically replacing any of those items stored in a site with people instead. It'd obviously need a custom made script for it (I don't think one such script exists currently), and I'm not sure how possible it is, since I've never touched anything worldgen related before. 🤔

Given your content, whether it still works needs to be seen but "construct-creature.lua by IndigoPhoenix" might fit your purposes because of the way it transfers the reagent material directly into it.
That does look pretty old, and I'm not sure how well it'll work, but I'm glad I stumbled upon it. I never realised/considered you could just straight-up edit the materials a creature is made up from. I was considering potentially picking up one of my old mod concepts that involves creating golems, and I was going to just cheat making them out of a particular material by colouring their body material based on the colour of the material used, but actually making them out of their material sounds better.

Though actually looking into it, it doesn't look like those changes to a unit's materials are actually saved, so you'd have to reapply them whenever they're loaded, which seems like potentially more effort than it's worth.

2) Would having the reaction emit smoke count as a product? The smoke wouldn't do anything, just serve as a product for purposes of needing a product. (And maybe for dramatic effect.)

4) Ahhh, I have zero coding experience so I'm not quite sure how to write such a script. I'm like a toddler who knows basic math but can't do anything past that to give a decent metaphor about coding.

Given your content, whether it still works needs to be seen but "construct-creature.lua by IndigoPhoenix" might fit your purposes because of the way it transfers the reagent material directly into it.  Im new to writing in DFhack too, but the workshop reactions are fufilled by inputting them (somewhere, anywhere) onto the dfhack.init file in a particular code string to execute when the game is loaded, usually referencing a seperate .lua with the code in it.

I like to use grown.lua (which i picked up as part of a older modification's dfhack spec) which applies a simple grown flag to the output which is useful for elf modifications. etc like a so. My particular example is to process cut logs, then restore them to be grown via elven means of... tree necromancy? Its nonspecific but it ought to work in a way that i can simply launder my logs through the shrine and then not alienate any traders later so long as im careful.

Location, then reaction-product-trigger (pretty typical if you've got DFhack of the latest version out the box, its simply referencing the scope from the DFfilefolder's position, and would change if you added another dfhack.init somewhere else) input a name from the reaction file, then the command references the actual code to apply in square brackets so it works.

The // is just a comment to keep track of what its meant to be doing and anything past // doesnt count as the code will stop reading.

Code: [Select]
modtools/reaction-product-trigger -reactionName DENDROMANTIC_REVIVAL -command [ grownwood.lua \\OUTPUT_ITEMS ]
Feel free to correct me anybody if i've actually got it wrong myself. Its all a opportunity to learn. Notepad++ application is probably the easiest way to open them to look inside any .lua file and also make relevant edits.

I do kind of want to make procedural wood ents now though. Thinking of the hideously strong dryads/ents i could make with custom trees, there's more than enough old abandoncode elf mods to finish it.

Oh!!! Thank you very much. This makes a lot of sense--but I only need one thing (A large gem) to make a rock person, and I'm not sure if you can leave out one thing in the code. I did think briefly about making the rock people bleed gold because the mental image of their scars resembling kintsugi would be cool, but it would be difficult in practice to hunt down literal gold just to expand the fort's population without exploits. I could instead just make it so that they need metal bars of any kind to act as "blood."
Logged
Whatchu gonna do when I'm fucking small
Like one inch tall
You won't see me coming at all

He or They pronouns

Atkana

  • Bay Watcher
  • [CURIOUSBEAST]
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #7 on: January 09, 2021, 07:14:02 am »

2) Would having the reaction emit smoke count as a product? The smoke wouldn't do anything, just serve as a product for purposes of needing a product. (And maybe for dramatic effect.)
So long as there's a PRODUCT in the reaction that gets made (i.e. that succeeds its probability roll), that's all that matters. It could be a random toy, a shoe, some splashes of water, or yes, a boulder of something that instantly turns to smoke for dramatic effect (actually, boulders and other things that can't have a quality rating are best, because you can get announcements when items with high qualities are produced, and you'd rather the products be discretely made).

FantasticDorf

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #8 on: January 09, 2021, 08:43:29 am »

2) Would having the reaction emit smoke count as a product? The smoke wouldn't do anything, just serve as a product for purposes of needing a product. (And maybe for dramatic effect.)
So long as there's a PRODUCT in the reaction that gets made (i.e. that succeeds its probability roll), that's all that matters. It could be a random toy, a shoe, some splashes of water, or yes, a boulder of something that instantly turns to smoke for dramatic effect (actually, boulders and other things that can't have a quality rating are best, because you can get announcements when items with high qualities are produced, and you'd rather the products be discretely made).

Of course, its all fun and games until the harmless water vapour smoke freezes on the spot or a lung damaged chokes on the fumes.  :P

Set the probability of success on the reaction to 0 as a alternative if you dont want a fancy additional thing and to just run the DFhack reaction is another tip i remember being told. Again with the discreetness applied.
Logged

LilyInTheWater

  • Bay Watcher
  • Me want bite. Me want plant corn dog delight.
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #9 on: January 11, 2021, 02:51:21 am »

So I'm looking at the construct-creature.lua script and I'm a little confused about this first bit.

Quote
Only materials actually used in the creature will be counted.  You're best bet is to simply define the modifiable tissue(s) near the top of the creature raw, before defining any other materials or tissues.
This might not be the way the materials are always loaded, further testing is needed.  But if you make a creature like this one it should work fine.

So if I put this as the first tissue,

Code: [Select]
[TISSUE:GEM]
[TISSUE_NAME:gem:NP]
[TISSUE_MATERIAL:INORGANIC:MORION]
[MUSCULAR]
[FUNCTIONAL]
[STRUCTURAL]
[RELATIVE_THICKNESS:1]
[CONNECTS]
[TISSUE_SHAPE:LAYER]
[TISSUE_LAYER:BY_CATEGORY:ALL:ROCK]

Will it just replace the MORION with the first reagent used?
Logged
Whatchu gonna do when I'm fucking small
Like one inch tall
You won't see me coming at all

He or They pronouns

FantasticDorf

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #10 on: January 11, 2021, 02:57:49 am »

To my vague understanding it'll be a input reagent on the reaction of the structural integrity of morion.
Logged

LilyInTheWater

  • Bay Watcher
  • Me want bite. Me want plant corn dog delight.
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #11 on: January 11, 2021, 07:07:05 am »

To my vague understanding it'll be a input reagent on the reaction of the structural integrity of morion.

I'm not quite sure I understand this response, haha. So will the game act as if the input reagent is the tissue the Morion is?
Logged
Whatchu gonna do when I'm fucking small
Like one inch tall
You won't see me coming at all

He or They pronouns

Nahere

  • Bay Watcher
    • View Profile
Re: Connecting lua scripts to reactions + related worldgen questions
« Reply #12 on: February 01, 2021, 06:13:26 pm »

Construct-creature doesn't actually work as intended:
So after playing around with your construct creature which is supposed to let you construct a creature out of any material I have found that you are actually changing an entire creatures definitions, not a specific units. Specifically, from line 1450

Code: (soulshuffle-constructcreature.lua) [Select]
for i=0,#u.body.body_plan.materials.mat_type-1,1 do
local matbase = dfhack.matinfo.decode(u.body.body_plan.materials.mat_type[i],u.body.body_plan.materials.mat_index[i])
local code = ''
if matbase.mode == 'creature' or matbase.mode == 'plant' then
code = matbase.material.id
elseif matbase.mode == 'inorganic' then
code = matbase.inorganic.id
end
local r_item = getReagentItemByCode(reaction,jobmats,code)
r_mat = nil
if jobmats[code] then r_mat = jobmats[code] end
if r_mat ~= nil then
local r_mat_index=r_mat.index
local r_mat_type=r_mat.type
u.body.body_plan.materials.mat_index[i] = r_mat_index
u.body.body_plan.materials.mat_type[i] = r_mat_type
end
end

body_plan is not different for different units. It is a raw based reference. If you make a ruby golem and then you make a silver golem, the ruby golem will also change into a silver golem. This method only works if you will only have one unit and may or may not persist through save/reload.

What.

It turns out you're right.

I guess I just never considered that a variable stored inside a unit could be an external reference.

That...basically destroys the entire point of the ConstructCreature script.

Now I'm upset.

...
Logged