GMS 2.3+ Creating object with interactive interface?


(For context, I started using GMS2 a couple of weeks ago so I'm not 100% familiar with GML or programming at all so bear with me!)

I've been following the Little Town tutorial for a game I'll be developing for my university thesis, where the player has to deliver specific items to the NPCs. So far the NPCs can recognize objects, and will react whether it's the correct item they need or not. Is it viable to create an object where the player can interact and select an item in particular?

It's going to be a cooking game where the player interacts with a plate, the interface pops up with diferent ingredients showing up. The player can select 2 or more of those ingredients, resulting in the required meal the NPC ordered. Is it viable to do so and how do you make that work?


At beginner level, the easiest approach probably would be to have all ingredients as instances. So when player interacts with the plate, it draws some interface graphics and then creates a bunch of ingredient object instances at appropriate locations on screen. Each ingredient would have code that toggles a selected status on/off when player clicks over it. Additionally, a "Cook" button instance would also have been created. When it is clicked, it checks which ingredients instances are in selected state, and checks against valid recipes. If they equal a valid recipe, player is given that food, and the cooking interface shuts down (stops drawing interface graphics, destroys all the ingredient instances and the cook button).


Without getting into the programming of the list itself, an easy although not terribly efficient way would be to store your recipes in a list of lists.

recipeList = ds_list_create()

meatPotatoRecipe = ds_list_create()

ds_list_add(meatPotatoRecipe, "Beef", "Potatoes", "Meat And Potatoes")

ds_list_add(recipeList, meatPotatoRecipe)
So now you've got a list of recipes, and one recipe in that list. When the player selects their ingredients and presses "cook", use a for loop to iterate through the recipeList list, like so:

var ingredient1 = [The first ingredient the player selected]
var ingredient2 = [The second ingredient]

for (i = 0; i < ds_list_size(recipeList) - 1; i++) {
    var tempRecipe = ds_list_find_value(recipeList, i)
    var ingredientCheck = ds_list_find_index(tempRecipe, ingredient1)
    if ingredientCheck != -1 {
        var ingredientCheck2 = ds_list_find_index(tempRecipe, ingredient2)
        if ingredientCheck2 != -1 {
            return ds_list_find_value(tempRecipe, ds_list_size(tempRecipe) - 1)
return "Failed Recipe"
This is mostly self explanatory, but some lines that may trip up a beginner:

"if ingredientCheck != -1" means "if the ds_list_find_index call found something". ds_list_find_index returns -1 if it didn't find anything.

"return ds_list_find_value(tempRecipe, ds_list_size(tempRecipe) - 1)" means "return the last item in tempRecipe", which here means the name of the recipe itself. I structured the data such that the name of the recipe is the last item in each recipe list, i.e. the last item in meatPotatoRecipe is "Meat and Potatoes", as seen above.

"return "Failed Recipe"" occurs after the for loop is over. It only happens if the for loop went all the way through recipeList and found nothing. Otherwise it would have returned something during the second ingredient check.

It would be better to store the selected ingredients in a temporary list and check against that rather than having those ingredientCheck vars, but that's another issue altogether. This will get you mostly where you need to be. You can worry about optimization later.