Recipes and qualities: Pointer Perplexion, or How Do I Make This Work?


I’ve coded myself into a corner here, because I am nowhere near a good enough programmer to figure this out on my own, apparently, and I am requesting some qualified advice to help me get over this hurdle.

Here’s what I am doing.

I’m rewriting the code that loads, processes, and displays crafting recipes, plus everything that the changes involved affect.
More specifically, I am changing the way recipe JSONs are written (while keeping the ability to load them the “old” way), so that it can allow tool-quality requirements to be optional, as well as allow them to require charges, and generally generalize the “recipe requirement” concept.

Segueing out of that is my rewriting of the function that processes the recipe and determines if the player has enough tools and components to craft it. And therein lies a snag.

My idea of doing this involves iterating through the items in the provided inventory. However, the “items” array (vector, set, whichever it is… map?) is private to the Inventory class, presumably for a good reason, so I can’t mimic the original function, and have to actually pass the processing over into a function in the Inventory class. I am reasonably sure that the code I wrote for the function is, in principle, at least capable of working to some extent. But this involves passing the actual recipe list - or, well, a pointer(reference?) to the recipe list, so that the function can assign values to the variables inside the various recipe requirements.

So the question is - how do I do this, exactly?

The pick_recipes function is where the call to the function originates:

With crafting_inv being a const inventory& crafting_inv, and *iter is recipe_list::iterator iter.

can_make_with_inventory is a bool game::can_make_with_inventory(recipe *r, const inventory &crafting_inv). It calls a bool inventory::can_make_recipe(recipe r) function, via return crafting_inv.can_make_recipe®;

How do I set up the can_make_recipe function, how do I call it in these circumstances, and how do I address the variables of r within it (i.e. r.variable or r->variable) so that it properly operates on the original recipe list, rather than a copy or who knows what else?

Any and all help greatly appreciated.

iter is recipe_list::iterator. iter actually calls the operator of the iterator, which returns a reference to the object that the iterator currently points to. As the recipes are stored as a list of pointers the operator* returns a reference to a pointer to a recipe.

inventory::can_make_recipe(recipe r)

This makes a copy and the function operates on the copy. Make it a reference and you can change the original object (nothing needs to be changed inside that function):

inventory::can_make_recipe(recipe &r)

But you have to call it as


Because here r is a pointer.

All hail BevapDin, the almighty explainer! :smiley:

It woooorks!


Well, some (humongous amount of) polish is required, and it’ll need rewriting to fit the formatting and whatever changes befell crafting.cpp in the meantime, but if it ends up merged you’ll be able to use recipes like this:

{ "type" : "recipe", "result": "nailboard", "category": "CC_WEAPON", "subcategory": "CSC_WEAPON_PIERCING", "skill_used": "fabrication", "difficulty": 0, "time": 1000, "reversible": true, "autolearn": true, "tools":[ [ {"quality":"HAMMER","level":1,"amount":1}, {"quality":"SCREW","level":1,"amount":1,"charges":20} ], {"quality":"SAW_W","level":1,"amount":1} ], "components": [ [ [ "2x4", 1 ], [ "stick", 1 ] ], [ [ "nail", 6 ] ] ] },

And the end result will look like this:

I still need to figure out how to do proper word wrap, but that’ll happen eventually. For now I need to make sure it counts all items and tools correctly.