Sign in to follow this  
imontheverge7

simple crafting system

Recommended Posts

Im trying to create a simple crafting system for my game. I havent come up with anything useful yet though. I was thinking that each time i pick up and item, i loop through my inventory and set a bool value to true. So if i need three items to create another, and i have them all in my inventory, an option will appear to make the item.

Does this make sense? Or is there an easier way to do this?

Share this post


Link to post
Share on other sites
For now, im just having the console write a line when all the items for a certain recipe are in my inventory, just until i know the crafting system works.

I have a list of inventory slots. The slot contains a parameter Item. So i can get my item from each slot.

How would i create a recipe for an item? I can use a bool value to determine if the object can be crafted but i dont understand how i would check each item in the inventory against the recipe

Share this post


Link to post
Share on other sites
I like the idea of having a RecipeItem class which holds variables Item and Amount, not unlike your itemstack class. My next problem is creating the actual recipe for an item. Say i have an item that needs a rock and twig. How do i store what that item needs in that items recipe?

Edit: i missed your list of ItemStacks. So i could use a list for each recipe. Great!!

Share this post


Link to post
Share on other sites

I have always disliked crafting system where you supposedly have to discover a recipe to use it (=look it up on the wiki because theres no logic to the crafting ingredients required to make something)

 

So I personally would prefer a very transparent crafting system. Basically an ingame list of all craftable items, structured logically. And highlight items you might want to craft (relevant to current situation), AND items you can craft or almost can craft (you have the ingredients in inventory).

Share this post


Link to post
Share on other sites

So I'm gonna post what I have so far. I've used the ideas you guys have posted and for now I'm just writing a line in the console when all the items I have in my inventory can make  hammer. I've set a breakpoint and all the variables are initialized, and the lists are populated as they should be. The only problem is that nothing is being written in the console, so I'm missing something here.

    public class RecipeItem
    {
        public Item Item;
        public int Amount;

        public RecipeItem(Item item, int amount)
        {
            this.Item = item;
            this.Amount = amount;
        }
    }
public class ItemRecipe
    {
        public List<RecipeItem> RecipeItems;

        public bool CanCraft;

        public bool CheckForItemsNeeded(Player player)
        {
            foreach (InventorySlot slot in player.PlayerInventory.itemSlots)
            {
                foreach (RecipeItem item in RecipeItems)
                {
                    if (slot.item == item.Item)
                        CanCraft = true;
                }
            }
            return false;
        }

        //in order to create a hammer, one rock, one twig, and one vine is needed
        public class HammerRecipe : ItemRecipe
        {
            public HammerRecipe()
            {
                RecipeItems = new List<RecipeItem>();
                RecipeItems.Add(new RecipeItem(new Twig(), 1));
                RecipeItems.Add(new RecipeItem(new Vine(), 1));
                RecipeItems.Add(new RecipeItem(new Rock(), 1));

                CanCraft = false;
            }
        }

Crafting system class

 private void LoadCraftingList()
        {
            CraftingList = new List<ItemRecipe>();

            CraftingList.Add(new survival.ItemRecipe.HammerRecipe());
        }

        public void CheckForAvailableCrafts(Player player)
        {
            foreach (ItemRecipe recipe in CraftingList)
            {
                foreach (InventorySlot slot in player.PlayerInventory.itemSlots)
                {
                    recipe.CheckForItemsNeeded(player);

                    if (recipe.CanCraft == true)
                    {
                        Console.WriteLine("true");
                    }
                }
            }
        }

Share this post


Link to post
Share on other sites

"class RecipeItem"

My main thought on this is there is nothing here specific to a recipe. Why not just have it as a generic Item & Amount class?

 

"public bool CanCraft;"

What is this?

 

"public bool CheckForItemsNeeded(Player player)"

Appears to be wrong. Should it not return true if the player has all the items, and false otherwise?

Currently it returns false always, and sets CanCraft to true if the player has any required item (rather than all), and regardless of quantity.

 

"slot.item == item.Item"

Not sure what language you are using, but since your using types/objects, it is likely that == here is not going to do what you want, since I suspect it is comparing specific instances of an item, not the type of item. e.g. in Java you should use "item.Item.equals(slot.item)"  (and override Item.equals appropriately), or if you only care about the types (not the data in the instances), use "item.Item.getClass() == slot.item.getClass()".

 

"public class HammerRecipe : ItemRecipe"

Personally id prefer to avoid the subclass...

 

"CheckForAvailableCrafts"

Makes even less sense. You start off well by iterating over the crafting list, by why iterate the inventory? CheckForItemsNeeded should already be taking care of that, your just calling it multiple times for no reason.

 

"if (recipe.CanCraft == true)"

Like I said, why does CanCraft exist? Use the return value of CheckForItemsNeeded.

Share this post


Link to post
Share on other sites
1) i created that class so its easier to make new recipes and keep the recipe and item seperate, it was easier for me to understand that way :p

2) That variable is there because...i think i left it there while trying out something else and didnt remove it? I dont really nees it.

3/)4Im trying to return true if all the items are matching the items in the recipe. Im using c# and comparing each Item that is in the recipe and inventory.

5)You're right on this one.

I think my problem here is that I'm not comparing my InventorySlot list to my RecipeItem list correctly, but i may be wrong

Share this post


Link to post
Share on other sites

Just be sure you're not "overcoding" things. You don't always need an elaborate class or several functions to handle something that could, technically, be stored in a handful of variables. I'm no expert, but the way I see it is that you need to ask what the computer is actually, at the end of the day, doing that produces the effect (or illusion, rather) of crafting. Technically, there's no crafting taking place here, it just emerges into that when certain things render according to certain conditions.

 

My two cents (rewrote this reply for clarity).

Edited by Madolite

Share this post


Link to post
Share on other sites

Look at 3 & 4 again...

//C#, compare by type, e.g. Rock == Rock, but Rock != Twig
typeof(slot.Item) == typeof(item.Item)

and like I said, the look logic is wrong as well.

 

Id suggest making an "int Inventory.GetCountOf(Item item)" to get how many of a given item is in the inventory, test that, once you are sure that works, use it to implement CheckForItemsNeeded with a single loop.

Share this post


Link to post
Share on other sites

SyncViews has mentioned many of the design flaws already. Here re some more:

 

1.) public bool ItemRecipe.CanCraft

 

a) ... should not be publicly writeable because there is no sense in setting it from outside the class, BUT ...

 

b) ... is not meaningful at all because for every change in the inventory the CanCraft may become obsolete

 

2.) public bool ItemRecipe.CheckForItemsNeeded(Player player)

 

a) ... needs an Inventory object but gets a Player object; that restricts flexibility and burdens with unneeded knowledge of what Player is

 

b) ... doesn't compute what you want (SyncView has mentioned it).

 

3.) public class HammerRecipe : ItemRecipe

 

a) Seconding SyncViews: Do this in a data driven way, not by inheritance! Even better: Do this in a data driven way, NOT by inheritance!! ;)

 


Be sure not to "overcode" things. You don't always need an elaborate class or several functions to handle something that could, technically, be stored in a handful of variables.

While this is true in principle ... Don't mix the representation with the data model and/or the mechanics. It is not over-engineering if data model, logic, and presentation are separated.

Share this post


Link to post
Share on other sites
Can you explaon what is.meant be data drivem and how it os better than inheritance in this case? From what i understand, youre saying instead of inherting, whenever i create a new instance of my Recipe class I populate the recipeitems list at the time of initialization. When i get off work ill make some more changes and post them

Share this post


Link to post
Share on other sites


Can you explaon what is.meant be data drivem and how it os better than inheritance in this case? From what i understand, youre saying instead of inherting, whenever i create a new instance of my Recipe class I populate the recipeitems list at the time of initialization.

Data driven means that there is no concrete, specialized sub-class for everything but the parametrization makes the difference.

 

You shall ask "how does an instance of HammerReceipe differ from an instance of, say, ScrewdriverRecipe? You'll notice that it is not really different. They may differ in the amount of distinguishable items needed, but that is given with List<ReceiptItem>.length() already. They may differ in the kinds of items and/or their amounts, but that is encoded in the ReceiptItem stored within the List<ReceiptItem> already. If you implement ItemReceipt as an object factory, then they differ from the type of crafted items, but that can easily be defined by using cloning an ItemReceipt.resultingItem template. They may differ in some kind of representations like a name or an icon, but those need to be attached anyway. So in fact, HammerReceipe and ScrewdriverRecipe and any XyzReceipe do not differ from each other except in their data! Using inheritance in such a case does nothing more than cluttering your code with many (many!) more classes, making it less maintainable.

 

Imagine a file that defines the game content. Let there be an entry that enumerates the items and their respective amount, and a routine that is able to process this. This routine can create all of the recipes without knowing any specialization of the basic ItemRecipe class, because the basic class is all what is needed.

Share this post


Link to post
Share on other sites

Ok I got rid of the inherited class and am just updating the recipe list when the CraftingSystem is created. But I still have no idea what I'm doing wrong in my CheckForItemsNeeded method. I'm looping through each InventorySlot and Item in RecipeItems and using item.Equals to compare them, and still I have nothing returning true. I'm lost tongue.png

Edited by imontheverge7

Share this post


Link to post
Share on other sites

 

While this is true in principle ... Don't mix the representation with the data model and/or the mechanics. It is not over-engineering if data model, logic, and presentation are separated

I rewrote my comment for clarity, I think I got myself misunderstood a little, here. Also, I wasn't implying that anyone was overcoding, I was just giving general advice.

Edited by Madolite

Share this post


Link to post
Share on other sites

Ok I got rid of the inherited class and am just updating the recipe list when the CraftingSystem is created. But I still have no idea what I'm doing wrong in my CheckForItemsNeeded method. I'm looping through each InventorySlot and Item in RecipeItems and using item.Equals to compare them, and still I have nothing returning true. I'm lost tongue.png

 

Show us the implementation of item.Equals.

Share this post


Link to post
Share on other sites

One of the surprising things I discovered when attempting to implement a crafting system in my current project is just how complicated a "simple" crafting system can be. I think the level of discussion and the number of responses here illustrates that quite well. 

 

On my inventory screen I have 5 crafting slots into which you can drop items. Every time something is dropped in a slot (or taken away), I quickly check all the known recipes and see if the items in the slots match any recipe. If so, I add a virtual item into the output slot that matches the output of the recipe. The player can then mouse over that item and find out what it is etc.

 

To that end, you may want to consider having the output also include a quantity rather than always imply a single item, as you can chop a log of wood into multiple pieces of firewood for example.

 

One thing that does bother me is the issue that Waterlimon raised which I'll dub "wiki syndrome" - where you have to consult the wiki to know the recipes or play the trial and error game. In my opinion, once you "know" a recipe, you should be able to activate it quickly if you have the required materials. That said, I haven't yet figured out a neat solution for that in my game, though it is on my todo list.

Share this post


Link to post
Share on other sites

If your relying on the players to put inputs into some sort of slots, I think your basically stuck with a wiki or in game browser. Personally I have always gone with having the crafting system work by just displaying the list of known recipes (possibly grouped) with an indication (e.g. highlighting) of what is currently possible. The user simply clicks on the things in this list to craft them (there is some more complexity with crafting stations that are not instant, but I still display the list on the ui screen).

Share this post


Link to post
Share on other sites

Hi.

 

 

What I like doing is a bit more work but I create a class that I define all the Objects Types in like, PLANT_TYPE has all things to do with plants.

 

class ObjTypePlant

{

        static std::vector<UINT> PlantType;

        static std::vector<std::string> TypeName;

public:

         static DefinePlantType(UINT baseindx)//the startting range you want for plants to start at

         {

                 //here you define your plants

                 PlantType.push_back(baseindex);//first plant type

                 TypeName.push_back("Tree1");

 

              //when you want to define a new plant type add it to the list

              baseindex++;//next type

 

             PlantType.push_back(baseindex);

             TypePlant.push_back("TheBushThatGiveLife");

 

             baseindex++;//next type

      }//end

 

 

//then setters and getters

static UINT GetType(UINT type)

{ UINT rt = -1;//sets it to max value a uint can hold

     //find type in list or return -1

}

 

static UINT GetType(std::string type)

{

//same but find the string name or return -1 for error

}

 

};

 

 

 

use like

 

#define PLANT_START_RANGE        3000

#define UNIT_START_RANGE           4000//

 

 

//called at init time

ObjectTypePlant::DefinePlantType(PLANT_START_RANGE);

 

there static so you can have them through out the code base

Share this post


Link to post
Share on other sites

once you "know" a recipe, you should be able to activate it quickly if you have the required materials. That said, I haven't yet figured out a neat solution for that in my game, though it is on my todo list.

 

Why not just make a recipe log (list) in some subpane of either the player's inventory or his journal/logbook (if you have that in the game)?

Then you just open the subpane, click on the recipe and it either shows it through text or some visual output in whatever area of that subpane that you assign as the output canvas.

Share this post


Link to post
Share on other sites
I'm trying to understand what your inventory looks like.

If I were you, I would add a "ghost" item of whatever could then be crafted to the inventory (provided you don't have too many of them). Just make it gray-scale or partially transparent (or something comparable). This item could be added which, if the player chooses it, will craft it and remove the others (it should just be sure to state that in the description).
I wouldn't give them anything they have to interact with when it happens (as others said, that would get annoying), but whenever they get a new ghost item added, I'd have it appear and fade over whatever area you access the inventory from so they know there's something new available.

A number of people have suggested fine methods for checking what items were available for crafting, etc. and it really doesn't matter too much if it's not the most efficient code in the world, so I won't weigh in on that.

Share this post


Link to post
Share on other sites

Just an update: I ended up creating a ListComparer class that compares the recipes to the items in my inventory and once I have enough items for the recipe, the icon of the object pops up in a little box. It works splendidly so far :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this