Modding

I made Cook Your Way coming from a very specific position as a foreign grad student in Canada. My experience as a migrant is privileged in many ways by the intersections I inhabit (cis, male, heterosexual) and I do not pretend to talk from it as a generalized experience or perspective. It is important to recognize and discuss the diversity of migrant experiences, the oppression we face in our differences and in our shared situations.

For this reason, I decided early on in the project to include some modification tools in the game, so that other folks can create tell different stories and play with other situations through the game system. This is key to make sure that voices beyond my own can pitch in and modify the conversations provoked by playing the game in different ways.

I also defend that games are tools for play, so they can be appropriated and changed to some level by people who are interested in what games create. Providing a modification system is a way to facilitate that process. It also acts as an educational material, that removes some of the black-boxing that happens in digital games, especially ones that involve custom hardware. By exposing and introducing ways to change the play experience, I hope that players (and others) can experiment and learn about game making. In the future, I hope to organize play & modding workshops too.

In general, the files that need to be modified are all in the folder CookYourWay_Data > StreamingAssets.

Recipes

A visa application in the Cook Your Way system consists of successfully preparing 3 recipes. They are defined in a CSV file, one recipe per row, with the following structure:

recipeId,recipeName,order,stepsSourceFile,expectedCompletionTime
couve,Couve mineira,0,00_test_recipe_steps.csv,200
calabresa,Calabresa,1,00_test_recipe_steps.csv,200
feijoada,Feijoada,2,00_test_recipe_steps.csv,300

The recipeId is a unique short name that is used when defining dialogue and recipe steps, while the recipeName is displayed to the players. The order defines the sequence of dishes, starting at 0. The stepsSourceFile is the full filename of the CSV file with the steps for that recipe. The expectedCompletionTime is the time limit that players have to complete this recipe.

Steps

Each recipe might have a number of recipe steps, which are defined on a separate CSV file, one step per row. The file must be on the StreamingAssets folder, with the same name as defined in the recipe_info file. Each recipe step is an action being made to an ingredient. There are 4 kinds of actions: add, chop, soak, and survey.

recipeId,inputId,ingredientId,targetQuantity,timeInterval,expectedCompletionTime,tolerance,sendToPot,actionDescription,potDescription
couve,soak,kale,10,0,30,0,true,"",""
couve,chop,kale,10,5,30,0,true,"",""
couve,survey,kale,0,100,30,0,true,"Are you sure?",""

The other columns of the CSV file control how the step is realized. The targetQuantity value defines how many times (for chop and add) or for how long (for soak) an action must be performed. The timeInterval controls the duration of each part of that action (e.g. one chop or picking a side on survey). The expectedCompletionTime defines a maximum time limit for this step. The tolerance value changes how precisely an action must be performed, and its used by chop and add actions. The sendToPot value add the ingredient to the pot to be cooked after the recipe step is complete; without ingredients in the pot, a recipe cannot be completed and served. Finally, actionDescription controls how the step will be displayed in an action box, while potDescription changes the text when the ingredient is added to the cooking pot.

Recipe steps are loaded via the [dialogue] system, using the loadRecipeStep command. The command works with the following structure: >> loadRecipeSted <recipeId> <inputId> <ingredientId>. Below is an example of that:

>> loadRecipeStep couve chop kale

The player can then either complete or fail the step. If they complete it, the dialogue system will load a node called <recipeId>_<inputId>_<ingredientId>_complete. If they fail, the system loads the node <recipeId>_<inputId>_<ingredientId>_failed.

Ingredients

To cook your recipes, you will need ingredients. Each ingredient consists of 2 parts: an ingredient image and some information that controls how an ingredient cooks and how it is displayed in-game.

Ingredient info

The information about all the ingredients in the game is in one CSV file, which you can edit in any text or spreadsheet editor. Each row represents one ingredient, and each column a different gameplay variable that defines it. You can see an example below.

id,mapping,cookingSpeed,temperatureMax,stirInterval
garlic,"456",0.1,300,2
kale,"345",1,300,5

The id is a unique name for each ingredient, which is used for many things like load its image or defining recipe steps. The mapping is a text that defines the unique combination of pins in that ingredient card (there is an example in the photo below). This value is used only by the custom controller; it is ignored when using the keyboard to play.

The cookingSpeed defines how long it takes to cook it when it is added to the pot and temperatureMax controls how much heat that ingredient can tolerate before getting burnt. The stirInterval controls how often this ingredient needs to be stirred when cooking (small numbers require more stirring).

Images

You can define your own image for your ingredients. The image for each ingredient is a separate PNG file, with a square proportion and a transparent background. I recommend a resolution of around 200 x 200 pixels. This image must be on the StreamingAssets folder of your game installation folder, with a filename with the pattern ingredient_<id>.png. Example: ingredient_garlic.png.

Dialogue

The events that happen during a Cook Your Way play session depend on what dialogue file was loaded. From this file (that ends with a .dia extension), you can make characters talk, recipe steps appear and show or hide different panels. The structure is based on two ideas: 1) each line in the dialogue file is either a character line or a command; and 2) you can organize lines in blocks called nodes, which can be started when you choose or automatically by the game in some special cases.

Nodes

The nodes that group character lines and commands should have unique names. You can reuse nodes in your narrative and they are important for creating branching. Nodes are defined by the syntax below:

---
node_id

A: A character line.
# this is a comment, it does nothing.
>> aCommand aParameter
===

The first node to be loaded has the id start. After this node, all the other nodes will be loaded based on your scripts. The only exceptions are some special cases, in which nodes are loaded automatically as a response to player actions in the game.There are basically two conditions for this automatic loading of nodes:

  • At the end of each recipe action: When completed, an action (like chopping or soaking) automatically sets-up a condition action_name_done to true when complete and starts a node recipeId_inputId_ingredientId_complete.
  • When a recipe changes its state: There are also special recipeId_failed, recipeId_ready, and recipeId_served nodes which are activated as soon as the dish you are cooking has either failed, completed preparing or been served.

Character lines

A character line can be “spoken” by different characters like judges and system panels. The options available are shown in the table below. When a line is said, it stays visible until the text is cleared using a command or a new line is loaded for that character.

SyntaxCharacter
A:Judge Michael Frontierini
B:Judge Bordom Ramsay
S:System panel
J:Both judges speak simultaneously
I:Id Procedure screen
N:Interview text

Commands

There is quite a variety of commands in Cook Your Way, for things such as customizing how text is shown to branching the story and controlling the pace of cooking. In general, a command starts with >> followed by the command name. After that, each command can have parameters that change how they work. Below you can find each possible command with an example and a description of its effects.

Text, display and pacing

Command / ExampleDescription
>> autoSpeed <seconds>
>> autoSpeed 5
Sets the duration for showing a a dialogue line.
>> clearTextErases text from characters.
>> delay <seconds>
>> delay 10
Sets a delay before continuing with next line/command.
>> enable <elementName> <true/false>
>> enable Checklist true
Enables/disables a panel or game element.
>> textSpeed <seconds>
>> textSpeed 0.1
The speed with which text appears on a screen text. Any value higher than 0 means an animated text, while `-1` sets the text instantaneously.

Narrative control and branching

Command / ExampleDescription
>> setCondition <condition_name> <new_value>
>> setCondition kale_little_salt true
Changes the value of the <condition_name> to <new_value>. It is used as preparation for the if command.
>> conditionalWait <seconds> <condition>
>> conditionalWait 10 chop_kale_finished
Delays flow for X seconds, exits immediately if the condition becomes true.
>> go <node_name>
>> go feijoada_start
Starts the desired node immediately.
>> block <true/false>
>> block true
Blocks all commands from happening.
>> if <condition> <node_id_true> <node_id_false>
>> if kale_little_salt kale_failed kale_ready
Starts <node_id_true> immediately if <condition> is true. Optionally, goes to <node_id_false> if <condition> was false.

Cooking system

Command / ExampleDescription
>> startRecipe <recipe_id>
>> startRecipe feijoada
Resets scores and loads
>> loadRecipeStep <recipe_id> <input_id> <ingredient_id>
>> loadRecipeStep couve chop garlic
Starts a recipe step (from the files loaded beforehand) that is defined by the combination of recipe_id, input_id, and ingredient_id.
>> applicationDeniedShows the final evaluation screen with a “denied” status.
>> applicationApprovedShows the final evaluation screen with an “approved” status.

An example scene


---
start
...
>> enable SystemPanel true
S: System loaded.
>> delay 2
>> clearText
>> enable SystemPanel false
>> autoSpeed 4
A: Hello, I am Michael Frontierini.
B: JUDGE Frontierini, for you.
A: Correct.
A: Prepare me a scrambled egg, applicant.
>> startRecipe scrambledEgg
B: Add the egg to the pot.
>> loadRecipeStep scrambledEgg add egg
===

---
scrambledEgg_add_egg_complete
...
B: Ok, now fill the pot with water.
>> loadRecipeStep scrambledEgg soak egg
===

---
scrambledEgg_soak_egg_complete
...
A: Are you ever going to heat the pot up?
>> delay 10
A: Why is this taking so long?
>> clearText
>> go scrambledEgg_failed
===

---
scrambledEgg_failed
...
J: Well, you can leave now.
>> clearText
>> applicationDenied
===

---
scrambledEgg_ready
...
B: Lower the heat and serve the egg.
>> clearText
===

---
scrambledEgg_served
...
A: Ok, that's a start.
>> clearText
>> enable Checklist true
>> delay 10
>> enable Checklist false
B: How difficult was that?
>> clearText
===