EDIT: I found a solution that works without needing to overhaul much of what I've done... and made myself feel like a fool, because it was at the top of my notes from when I started this project a week ago.
A dictionary containing names and IDs of items will exist, the game will add the ID of any given item to the mixing pot list, sort them in numerical order, and compare the result to a recipe dictionary.
I'll leave the original question here in case anyone else happens to have my weirdly specific problem.
The basic problem I aim to solve is a system in which the player can add ingredients to a mixing pot, click a button, and the game will read the list of ingredients and return a potion (or any other item, but I'm speaking on potions for simplicity's sake). The recipes for potions can get somewhat specific, and potions may need multiple of specific ingredients. The player might also add ingredients in an arbitrary order, and I want to account for that.
My original plan, when I started this project, was for each item to be loaded from a JSON or something, where they'd have a formID based on their list position. This formID would be taken for all the items thrown in the mixing pot, sorted, then checked against a dictionary of all craftable items to find what potion was made.
The problem I've run into, however, is that the detail and scale of my item system has grown to the point where each item is its own programmed object interfacing with a list of traits, each of which is their own programmed object with an interface for determining their parent items' function. For a clearer explanation, the structure I've gone with derives from this post: https://gamedev.stackexchange.com/questions/147873/creating-a-robust-item-system
Constructing things in this way allows for me to have an immense amount of flexibility in what any given item can do, what can be done with it, and what it can interact with. However, I can't be certain of the exact number of components or properties any given item should have, which makes building a JSON a bit complicated. I'm willing to do it, but I'm trying to poke around for options.
The way I see it, I could either restructure my items from the ground up to load from some sort of database file (which I feel would take away from some of the control I have over the unique function, interactivity, and variety of each given item) for the FormID method, or I could do something else.
The only other ideas I've had so far are adding some sort of FormID manually (which seems like a pain to keep track of), or taking the item name strings from the list of items in the pot, sorting them alphabetically, concatenating them together, and doing a dictionary sweep that way, but I feel like that would be far from ideal. I'm somewhat new to this particular aspect, but I'll do what I can to answer questions.
CodePudding user response:
I recommend the database approach.
At first glance I see it consisting of 3 Tables.
Potion table
this is where you would store any intrinsic information that all potions share like a Name
, you can also store any traits here in one column using JSON
.
Ingredients table
this is where you would store all possible ingredients.
Potion_Ingredients table
this is a relational table that links any number of ingredients to any number of potions.
Example of a potion in the DB.
ID| NAME |TYPE | EFFECT
1 | Regen Potion |Regen | {"HP":"50","RegenPerTick":".5"}
The Name
will be used for display purposes.
The Type
will be used by the Consumer
to determine how to handle the Potion.
The Effect
will be used in context with the Type
to act in a general way.
Using JSON in this situation would allow you to store any number of effects per potion.
CodePudding user response:
This post is all over the place, to the point that I can't really tell what you're asking about. You start out talking about crafting and items, so I thought it would be about how you check a list of ingredients against a list of recipes, but then you pivot to traits and deserializing from JSON, but then you provide an example of a healing potion and I can't tell why, then you seem to go back to deserializing and finally back to ingredient matching.
I think it would help you a lot to outline what you're trying to do with a sequence diagram or similar and try to break down your approach into manageable parts. The ingredient matching doesn't have anything to do with deserializing, which in turn shouldn't really have much to do with your possible potion types.
In general, I would urge you to respect encapsulation. When you say:
each of which is their own programmed object with an interface for determining their parent items' function.
that's a big screaming red flag to me. Why would a potion know about a sword or a scythe or a maul or a mace or a halberd etc. etc. A potion just knows it gives 5 to attack for 40 seconds. It's up to the user to know how to use it. Using an attack potion on bracers or boots doesn't do anything because they don't implement the IAttack interface, etc., but because it's an item it still implemented the IItem interface which means it can ApplyPotion(). The potion still gets used, it just gets lost (fizzles).
Traits or modifiers, like a fire opal instead of a regular opal, etc., are just bonuses. They should still count as their base ingredients (opal) for the purposes of ingredient checking, but when you make the potion you aggregate the bonuses on all ingredients and apply them to the finished product. You can have it such that multiple bonuses don't stack, or they do, or they do to an extent, or there could be tiers of bonuses like Fire I, Fire II, etc.
For crafting, you could make a string or int be the key in a dictionary, and you can build that key by assigning each ingredient class its own location, so ones indicates the number of feathers, tens is opals, hundreds is scales, thousands is gold, etc., such that a spell of 1201 would be one piece of gold, two scales, and one feather.
Maybe instead of a dictionary that returns subclasses of Potion you could use a switch statement in a PotionFactory that just configures a single base Potion class. If it doesn't find a match the default case could return null and you fail to build, or you could destroy all the ingredients, etc.
Deserializing is relatively straightforward when you use something like XML if you just make each component responsible for deserializing itself. Load the XML file, and when you get to a Potion tag you instantiate a new potion then hand the XML reference to the Potion. The Potion knows what fields it has and which are required and which are optional. Any classes that Potion needs also deserialize themselves, so each time you hit a Bonus tag you'd instantiate a Bonus, add it to the Potion bonuses, and hand the XML reference off to the Bonus to deserialize whatever it needed. This is almost like a recursive function - it goes as deep as it needs to go.
Anyways this is kind a rambling answer to a rambling question, but hopefully it helps point you in some better directions.