Counting specific items crafted.

Unofficial support for the creating and editing of metas.
HittingSmoke
Posts: 28

Counting specific items crafted.

Post #1 »

Still working on the crafting meta and I've got the basic logic worked out for a dependency tree I think.

In the mean time, I need to figure out how to count the number of items crafted.

This is the meta right now with Bread and Dough as placeholders:

An attempt at human readable formatting:

Bread / Sets recipe ingredients as variables, calls CraftLoop state

Always
All:
  • ExprAct setvar{use, Baking Pan], ExprAct setvar{on, Dough]
  • Call: Craftloop, return to: CraftLoopReturn
CraftLoop / If ingredients exist, craft

Expr getobjectinternaltype[wobjectfindininventorybyname[getvar[use]]]==7&&getobjectinternaltype[wobjectfindininventorybyname[getvar[on]]]==7
ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]]

CraftLoop / If ingredients are missing, sets meta state for missing item

getobjectinternaltype[wobjectfindininventorybyname[getvar[use]]]!=7
All:
  • ExprAct setvar[need, getvar[use]]
  • ExprChat \/vt setmetastate +getvar[need]
getobjectinternaltype[wobjectfindininventorybyname[getvar[on]]]!=7
All:
  • ExprAct setvar[need, getvar[on]]
  • ExprChat \/vt setmetastate +getvar[need]
CraftLoop / Monitor rule changes back to original recipe state when dependency has been crafted

All:
  • Second in state >= 2
  • Expr getobjectinternaltype[wobjectfindininventorybyname[getvar[need]]]==7
Return From Call

CraftLoopReturn / Transition rule from called state to original recipe state. Allows returning to a state from a call using a variable

Always
ExprChat \/vt setmetastate +getvar[capturegroup_item]

Default / Listener. Supports the !make and !reset commands.

ChatMessageCapture ^(\[[A-z]+?\] |)You (say|says|tells you), \"!make (?<amount>[0-9]*) (?<item>.*)\"$
All:
  • ExprAct setvar[capturegroup_amount, cnumber[getvar[capturegroup_amount]]]
  • ExprAct \/vt setmetastate +getvar[capturegroup_item]
ChatMessage ^(\[[A-z]+?\] |)You (say|says|tells you), \"!reset\"$
All:
  • ExprAct setvar[capturegroup_amount, 0]
  • ExprAct clearvar[capturegroup_item]
  • Set Meta State: Default
There is also a Dough state in the current meta, but it's identical to bread except for the name and ingredients.

So this works, currently, to make bread with just flour, water, and a baking pan in your inventory. I have write some logic to gracefully error when a base component or tool is missing.

Currently it just loops infinitely until it runs out of base components then resets to default. I would like it to loop until it has made capturegroup_amount of capturegroup_item.

My first idea was to use a InventoryItemCount condition. Can't use variables. Would require a rule for every single item with hard coded names and amounts.

Second idea was a countdown in the CraftLoop state. Every run would do capturegroup_amount-1. However that would run on every item, including dependencies.

Third idea was a ChatMessageCapture watching for item names in chat, but the success messages vary from item to item too much and I can't use a variable in a ChatMessageCapture. Most of my problems seem to stem from not being able to use variables outside of expressions which is why this meta is just expression bukakke.

Fourth idea was a countdown in the recipe rule itself. However the way the loop works it doesn't craft an item every time because of dependencies. It could loop through the recipe rule multiple times before it actually crafts something. One idea is addin to capturegroup_amount when a dependency is crafted and subtracting whenever the capturegroup_item rule is run but I don't quite have my mind wrapped around how to do that yet.

Any suggestions on how to solve this counting issue? It would be easier if there was a way to count items with a meta expression but I don't see any method do actually get an item count, just information about the item itself.

Dmdtt
Moderator
Posts: 271

Post #2 »

would this work? adding +1 to a counter every time the crafting action takes place

in craft loop
ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]];setvar[Counter, getvar[Counter]+1]

then you can use that counter to compare to the cnumber[getvar[capturegroup_amount]]

HittingSmoke
Posts: 28

Post #3 »

Dmdtt wrote:would this work? adding +1 to a counter every time the crafting action takes place

in craft loop
ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]];setvar[Counter, getvar[Counter]+1]

then you can use that counter to compare to the cnumber[getvar[capturegroup_amount]]
Would that count every time something was crafted though including recipe dependencies?

I think that would require a rather complex addition and subtraction scheme. Like I mentioned my idea was to just do a countdown. But to count a tick every time something is crafted I would have to add 1 for every dependency crafted and subtract one for every item crafted. I think it could work, but I haven't thought out the best way to do it yet.

Dmdtt
Moderator
Posts: 271

Post #4 »

perhaps I am reading it wrong but from what I understand.

ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]]

only crafts at the final step in your example baking pan on dough so if you were to add the counter only for that step

ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]];setvar[Counter, getvar[Counter]+1]

it would accurately keep track of how much bread you have made.

if however you are using the same loop for both crafting dough and crafting finished product of bread that of course wouldn't work.

have you thought of using 2 separate crafting loops? one for dependencies(I'm assuming in your case Dough is your dependency) and a second one for finished product? that way it is easier to keep track of each one and how many of each item you have crafted.

HittingSmoke
Posts: 28

Post #5 »

Dmdtt wrote:perhaps I am reading it wrong but from what I understand.

ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]]

only crafts at the final step in your example baking pan on dough so if you were to add the counter only for that step

ExprAct actiontryapplyitem[wobjectfindininventorybyname[getvar[use]], wobjectfindininventorybyname[getvar[on]]];setvar[Counter, getvar[Counter]+1]

it would accurately keep track of how much bread you have made.

if however you are using the same loop for both crafting dough and crafting finished product of bread that of course wouldn't work.

have you thought of using 2 separate crafting loops? one for dependencies(I'm assuming in your case Dough is your dependency) and a second one for finished product? that way it is easier to keep track of each one and how many of each item you have crafted.
It is the same loop for all crafting. CraftLoop is the engine of the whole thing. The recipes set the ingredient variables and call the CraftLoop, which crafts the item. Using one for the entire thing was my solution to the recursion problem. That being, how do I get the meta to first craft Dough when I ask it to craft Bread. It just goes down the chain until it finds something it can craft, then it starts all over. The meta doesn't know the difference between crafting the item and crafting the dependency.

For now I've solved it by subtracting 1 from capturegroup_announce every time an item is crafted, then adding 1 every time a missing item is detected. Then if capturegroup_amount<=1 on each craft loop I set Default. I'm not sure if this math will scale, but it works for my bread test.

I don't like it because it doesn't account for failures and feels fragile. I would still like it to parse chat but I don't think that's practical. I'll probably just have to give the current implementation a thorough testing and settle with it if it doesn't break.

Dmdtt
Moderator
Posts: 271

Post #6 »

thought of another solution to your counting problem, adding and subtracting will only work for a 2 step process it wont work for things like leader horns that require 3 crafts to get to the final craft on a finished product.

All{
Expr getobjectinternaltype[wobjectfindininventorybyname[getvar[use]]]==7&&getobjectinternaltype[wobjectfindininventorybyname[getvar[on]]]==7
Expr getvar[use]==getvar[FinalUse]
Expr getvar[on]==getvar[FinalOn]}
Action
ExprAct setvar[Count, getvar[Count]+1]

place that just above the craft action so it triggers anytime the proper item is being crafted for finished product. and in your initial recipe state setvar[FinalOn, Dough] and setvar[FinalUse, Baking Pan] it will mean 2 more variable to keep track of but it works for any process regardless if it is 2 steps or 10.

HittingSmoke
Posts: 28

Post #7 »

Dmdtt wrote:thought of another solution to your counting problem, adding and subtracting will only work for a 2 step process it wont work for things like leader horns that require 3 crafts to get to the final craft on a finished product.

All{
Expr getobjectinternaltype[wobjectfindininventorybyname[getvar[use]]]==7&&getobjectinternaltype[wobjectfindininventorybyname[getvar[on]]]==7
Expr getvar[use]==getvar[FinalUse]
Expr getvar[on]==getvar[FinalOn]}
Action
ExprAct setvar[Count, getvar[Count]+1]

place that just above the craft action so it triggers anytime the proper item is being crafted for finished product. and in your initial recipe state setvar[FinalOn, Dough] and setvar[FinalUse, Baking Pan] it will mean 2 more variable to keep track of but it works for any process regardless if it is 2 steps or 10.
Oh that's perfect and simple! Thanks. I don't mind more variables. I just want to keep everything outside of the craft loop very simple and manageable for scaling purposes.

HittingSmoke
Posts: 28

Post #8 »

Dmdtt wrote:thought of another solution to your counting problem, adding and subtracting will only work for a 2 step process it wont work for things like leader horns that require 3 crafts to get to the final craft on a finished product.

All{
Expr getobjectinternaltype[wobjectfindininventorybyname[getvar[use]]]==7&&getobjectinternaltype[wobjectfindininventorybyname[getvar[on]]]==7
Expr getvar[use]==getvar[FinalUse]
Expr getvar[on]==getvar[FinalOn]}
Action
ExprAct setvar[Count, getvar[Count]+1]

place that just above the craft action so it triggers anytime the proper item is being crafted for finished product. and in your initial recipe state setvar[FinalOn, Dough] and setvar[FinalUse, Baking Pan] it will mean 2 more variable to keep track of but it works for any process regardless if it is 2 steps or 10.
EDIT: Figured it out. Just had bad rule placement. Editing in the solution below.

Actually that's not going to work. Since FinalOn and FinalUse are set in the recipe it would be overwritten for every component crafted because there is no differentiating between the CraftLoop run with the goal item or the components for the goal item.

You gave me an idea though. There is a way to differentiate.

The CraftReturn state is only returned to from the call when an item is actually crafted and the "need" state (which switches to the needed component state when a missing component is detected) is only set when a missing component is detected.

So, when the CraftReturn state is run while "need" is set, a component is being crafted.

I tried setting a rule in CraftPause which is a state to allow the half second or so required to actually craft an item.

Condition:
Expr testvar[need]==False

Action:
ExprAct setvar[capturegroup_amount, getvar[capturegroup_amount]-1]

...with a clearvar[need] running always in the return state.

Now the count will tick down every time the need variable has not been set to craft an item.

The logic is all working and I've successfully imported recipes so I'll make a beta thread for this meta soon.