[Modder's Mod] Custom Crafting Requirements

Kai Monkey’s

Custom Crafting Requirements

Steam Link

This is a “Modder’s mod”, that it, it does not do anything itself, but extends the way that modders can easily change the game.

Specifically this mod adds the ability for recipes to have additional requirements that the crafter must fulfill. These requirements can be anything that can be expressed in Lua! It does this with just two new fields for recipes: “custom_requirement” and “custom_requirement_string”

For example:


{

"custom_requirement": "radiant.entities.has_trait(crafter, 'stonehearth:traits:cultist')",

"custom_requirement_string": "Requires a cultist"

}

Adding or mixing this into any recepe will mean that the crafter must have the correct levels in the job AND have the cultist trait.

Other examples you could include in your mods are:

  • Only craftable by sad hearthlings: crafter:get_component(“stonehearth:happiness”)._sv.mood == “glum”

  • Only craftable by hearthlings with spirit 6 or above: crafter:get_component(‘stonehearth:attributes’):get_attribute(‘spirit’) >= 6

  • ect.

I may create a showcase for this mod soon, depending on how much interest there is.

Just remember that if you use this mod in your mod, make sure you either copy the code into your mod (not recommended), or ensure this mod is listed as a required item on your mod!

10 Likes

This is an amazing mod!
I can already imagine several uses of it :merry:

And it also reminds me of something… Although not the same - might be similar enough - to something I was trying to do for ACE. I might message you about it soon :jubilant:

@DaniAngione I look forward to your correspondence! I must admit the lengths I had to go to to figure out how to run a lua script from a config file was a lot more than I expected it would be (it was a little more than just a simple eval(str))

Also, I think it would be fun if anyone can think of other fun one line checks I could add to example list! If I make other mods based on this principle I could reuse them

1 Like

Note: this is kind of stream-of-consciousness, just getting ideas/thoughts out there.

I assume a modder could do something like this:

{
"custom_requirement": "radiant.mods.load_script('my_namespace.custom_requirements.this_particular_requirement'):eval(crafter)"
}

and then in a my_namespace/custom_requirements/this_particular_requirement.lua have code like this?

local CustomRequirement = class()

function CustomRequirement:eval(crafter)
    local can_craft = false
    -- get crafter's town to perform checks for wealth/buffs
    -- combine multiple checks with ors/ands into can_craft
    return can_craft
end

return CustomRequirement

Alternately, since white space can come in any form in Lua, you can replace all the line breaks in a function with spaces and put the whole thing in "custom_requirement", but it could be pretty ugly:

{
-- Lua psuedo-code:
"custom_requirement": "for each thing do if service:function(thing) then return true end end"
}

Another option would be to have separate files that contain all the functions, and these files are loaded up via a JSON in which people can mixinto their own function file references (so they don’t have to monkey-patch a single targeted Lua file themselves): then this mod would load up that JSON file at the beginning, identifying all the Lua files it needed to load up and index them by keys ('my_namespace:my_function' should be enough). Then you could do something like this:

{
"custom_requirement": "self:custom_functions['my_namespace:my_function'](crafter)"
}

But now that I think of it, this makes it difficult for other people to patch those functions; they would have to create new functions and override the "custom_requirement" setting everywhere that particular requirement was being used (imagine that they added a custom trait that was similar to “cultist” and they wanted all recipes that required a cultist to also allow crafting if that trait were present). I think taking advantage of the infrastructure provided to us by Radiant with the manifest system could help: having the modders who use this define aliases, functions, that sort of thing in their manifest, and then other modders in turn could monkey-patch or override those aliases/functions/files with their own.

But as @max99x would say, it depends on how permissive you want your API to be, and I tend to get overly zealous in giving people tools/access. :stuck_out_tongue:

Edit: An example for handling custom functions in an organized fashion would be to do something like the heatmap (client) service that I wrote for ACE, which is essentially what I described with the JSON index file, but that’s a working example you can look at (it includes initialization callback functions and should allow hot-loading heatmaps that aren’t included in the keys JSON, though I never tested that, and looking at it now I think there might be some issues with the combination of callback functions and hot-loading in particular).

1 Like

I’m not overly sure of what the problem is you’re trying to solve here? Because I feel you are greatly over estimating the complexity of the types of lines that a modder’s could choose to use here. These will only ever be concepts that can be expressed in 5-6 words (for lack of room in the window if nothing else!)

But as it is, I imagine most possible use cases just involve reading the output of character component attributes and comparing them to a desired value(s)

This is why I made the choice to use a line of code, not a reference to a lua file.

Edit: Also, if your sole issue here is the ability to patch existing custom requirements (which honestly I would bet money may never arrise) that becomes easy if you have one file “require_cultist.json” which you mix-into all your recpie, which is how I intended it to be used

Not trying to solve any problems, just imagining ways the system could be used (e.g., for situations where the condition is a little more complex than what can easily be expressed in a short line of code).

I like your idea of having each of the requirements be specified in its own JSON, and then having the recipes that use that requirement mix it in. It looks like you’re limiting it to a single requirement? I suppose there’s not much UI space for displaying multiple custom requirements without, e.g., displaying an ellipsis and then more complete text in a tooltip, but I can imagine having the capacity for multiple conditions being rather useful.

1 Like

I sent it on Discord but I’m afraid I have two Kaimonkeys over there… So I dunno which one is the right one and sent to the one we talked before - let me know if you didn’t get it and I’ll send to the other :stuck_out_tongue:

I’m a little disappointed that this (as far as I know) never got used by anyone :disappointed:

In my case it was a case of “cool, but I’m too rubbish at lua to use it” which would probably also be the case for some others… :confused:

I probably should make/should have made a punch of premade mixins that could just be referenced or modified :woman_shrugging:

Like, one for each trait, one for each stat, one for each mood, one for each job (I.e. a sword that you need blacksmith AND Knight levels for), one for each Faction and… Idk… Time of day? Weather? Season?

Having them all off the shelf, just requiring adding @mixin would probably made it more popular, and only require lua if you want to go outside of that

Edit: if this message gets enough likes or someone PMs me with a polite request I’ll sit down and do this, but I kinda assume the moment has past?

1 Like

Not sure, personally I think it would be cool to, for instance, be able to define “can only be made at night”
For instance for potions, but I wouldn’t want you to go to the trouble just for thst. Plus I’m on a holiday atm, don’t really have anything going modding wise atm, just Sun and French quisine :stuck_out_tongue:
But yes I highly suspect if people could use json instead of lua it would be more popular

1 Like