GameMaker Basic crafting system

T

Thijmen Langendam

Guest
Hey guys, so i currently have a basic inventory shown below, where the left side is the inventory and the right side is the crafting menu.



Now how it currently is set up is that there is a grafting grid which is 2 wide and 32 high.
This crafting grid above is setup that the top left square is cell 0, the top right square is cell 7 and then the one below the top left one is cell 8 etc.
This is connected to the crafting grid in the same manner.

Now the player can only place in cells 0, 1, 8, 9, 16, 17, 24 and 25 and not in the others, but can grab from those.
There are 4 non-functional cells, 3, 10, 18 and 26 which is the column with the arrow in it.
The other cells are all the crafting output.

Now i want to make a crafting mechanism such that it will show all crafting possibilities with the input items,
so if i have as input raw wool and a stick, then the output will show toothpicks, a torch and a piece of cloth (random example that makes no sense) because the stick can be turned in to toothpicks,
the raw wool into cloth and the stick + wool into an non-lit torch.

How could i create such a mechanism such that it is still decently fast to check all possible recipes and display all possible output items.
If the player decides to take one of the output items, it should remove the resources that were needed to create that item from the input and of course the item itself from the output.
 

GMWolf

aka fel666
[editing]
ignore the spoiler, i forgot gm checks references
a quick way to do this would be to give each item an ID.
then, create an array with each index representing a crafting slot.
so if you have wool be 8, and stick is 4, and you crafting slot has "wool". "stick", "stick", then your arrya would be [8, 4, 8];

now build a big ds_map with arrays as keys, and the items as a result:
Code:
craft_map = ds_map_create();
craft_map[? [8,4,8]] = 16; //maybe 16 is torch
then, you cna just find if you crafted something like so:
Code:
var c = craft_map[? crafting_array];
if (!is_undefined(c)) {
  //we crafted something!
}

what you want to do is give each item an ID.
for example, stick can be 1, and wool can be 8.

then, you can build a string from your crafting grid like so:
Code:
var crafted = "";
for(int i = 0;  i < grid_size; i++) {
 if (slot[i] != empty) {
    crafted += string(slot[i]) + ",";
  } else {
     crafted += ",";
  }
}
now, you can make a big ds map containing recipes:
Code:
 var craft_map = ds_map_create();
  craft_map[? "1,1,8"] = 16; // stick, stick, wool makes torche (16)
  craft_map[? ...] = ...;
then to check, just do:
Code:
var crafted = "";
for(int i = 0;  i < grid_size; i++) {
 if (slot[i] != empty) {
    crafted += string(slot[i]) + ",";
  } else {
     crafted += ",";
  }
}

var c = craft_map[?crafted];
if (c!= undefined) {
 //you crafted C!
}
 
Last edited:
T

Thijmen Langendam

Guest
[editing]
ignore the spoiler, i forgot gm checks references
a quick way to do this would be to give each item an ID.
then, create an array with each index representing a crafting slot.
so if you have wool be 8, and stick is 4, and you crafting slot has "wool". "stick", "stick", then your arrya would be [8, 4, 8];

now build a big ds_map with arrays as keys, and the items as a result:
Code:
craft_map = ds_map_create();
craft_map[? [8,4,8]] = 16; //maybe 16 is torch
then, you cna just find if you crafted something like so:
Code:
var c = craft_map[? crafting_array];
if (!is_undefined(c)) {
  //we crafted something!
}

what you want to do is give each item an ID.
for example, stick can be 1, and wool can be 8.

then, you can build a string from your crafting grid like so:
Code:
var crafted = "";
for(int i = 0;  i < grid_size; i++) {
 if (slot[i] != empty) {
    crafted += string(slot[i]) + ",";
  } else {
     crafted += ",";
  }
}
now, you can make a big ds map containing recipes:
Code:
 var craft_map = ds_map_create();
  craft_map[? "1,1,8"] = 16; // stick, stick, wool makes torche (16)
  craft_map[? ...] = ...;
then to check, just do:
Code:
var crafted = "";
for(int i = 0;  i < grid_size; i++) {
 if (slot[i] != empty) {
    crafted += string(slot[i]) + ",";
  } else {
     crafted += ",";
  }
}

var c = craft_map[?crafted];
if (c!= undefined) {
 //you crafted C!
}
Allright, but would this work if i only wanted to craft the toothpicks even though the raw wool is in the input? Or would you say it's better to just display the items craftable with the current item combination.

Also, the input can be stacks, so for example 2 sticks and 3 wool, how would i approach it knowing this?
Maybe not an unimportant thing to say, any of the input slots can be used, so the input can be:



Where the red 1 is just the id of wool and blue 2 is the id of wood. (paint skills)

And then for example:
- 1x wool + 2x wood = torch
- 2x wool = cloth
- 1x wood = 10x toothpick
 

GMWolf

aka fel666
So if i understand correctly, the order does not matter, just the quantity of items?

in that case, you could do something a little like this:
Code:
craft_map[? "3x1 2x2"] = torch; //3 times wool, 2 times wood 
craft_map[? "1x2"] = pick; //1 time swood makes picks
//items must be ordered from lowest id, to highest id
Code:
var crafting_map = ds_map_create();
var crafting_items_list = ds_list_create();
for(int i = 0; i < craft_slots; i++) {
 var item = craft_slots[i];
 var item_count = craft_slots_count[i];

 if (crafting_map[? item] == undefined) {
   crafting_map[? item] = item_count;
   ds_list_add(crafting_items_list, item);
 } else {
   crafting_map[?item] = item_count + crafting_map[? item];
  }
}

ds_list_sort(crafting_items_list);

var crafting_string = "";
for(int i = 0; i < ds_list_size(crafting_items_list); i++) {
   var item = crafting_items_list[| i];
   var count = crafting_map[? item];
   crafting_string += string(count) + "x" + string(item);
    //add the space
   if (i < ds_list_size(crafting_items_list) - 1) {
      crafting_string += " ";
   }
}
hope this helps!
 
T

Thijmen Langendam

Guest
So if i understand correctly, the order does not matter, just the quantity of items?

in that case, you could do something a little like this:
Code:
craft_map[? "3x1 2x2"] = torch; //3 times wool, 2 times wood
craft_map[? "1x2"] = pick; //1 time swood makes picks
//items must be ordered from lowest id, to highest id
Code:
var crafting_map = ds_map_create();
var crafting_items_list = ds_list_create();
for(int i = 0; i < craft_slots; i++) {
 var item = craft_slots[i];
 var item_count = craft_slots_count[i];

 if (crafting_map[? item] == undefined) {
   crafting_map[? item] = item_count;
   ds_list_add(crafting_items_list, item);
 } else {
   crafting_map[?item] = item_count + crafting_map[? item];
  }
}

ds_list_sort(crafting_items_list);

var crafting_string = "";
for(int i = 0; i < ds_list_size(crafting_items_list); i++) {
   var item = crafting_items_list[| i];
   var count = crafting_map[? item];
   crafting_string += string(count) + "x" + string(item);
    //add the space
   if (i < ds_list_size(crafting_items_list) - 1) {
      crafting_string += " ";
   }
}
hope this helps!
I get what you mean, but how would the following line of code work when there's more than just 1 piece of wood?
Because that would mean that the so called crafting string wouldn't only be ["1x2"] but for example ["2x1 1x2"], this should yield that the player can craft both picks as well as a torch because they're both combinations of the crafting string.

Code:
craft_map[? "1x2"] = pick; //1 time swood makes picks
 

GMWolf

aka fel666
I get what you mean, but how would the following line of code work when there's more than just 1 piece of wood?
Because that would mean that the so called crafting string wouldn't only be ["1x2"] but for example ["2x1 1x2"], this should yield that the player can craft both picks as well as a torch because they're both combinations of the crafting string.

Code:
craft_map[? "1x2"] = pick; //1 time swood makes picks
I can see three solutions:
  1. Just do it inneficiently
  2. Rethink your game design
  3. Use a full fat DBMS system.
 
T

Thijmen Langendam

Guest
I can see three solutions:
  1. Just do it inneficiently
  2. Rethink your game design
  3. Use a full fat DBMS system.
Yeah thats what i thought, i'll just display the recipe's that are available with just the items you put in (or multiples of it)

So if 1 log makes 2 picks, then if you put in 3 logs it can make 6 picks.
 
Top