|
52 | 52 |
|
53 | 53 | /// Core function that checks if a object meets all the requirements for certain |
54 | 54 | /// recipe actions. |
| 55 | +/// |
| 56 | +/// This is one of the thornier and grosser parts of the cooking system and most |
| 57 | +/// people working with it or implementing recipes should never have to look at |
| 58 | +/// this. The core idea is: |
| 59 | +/// |
| 60 | +/// * we keep track of what recipes are still valid outcomes by testing the used |
| 61 | +/// item against the list of recipes which are valid so far. |
| 62 | +/// * each valid recipe is at a certain step, and check the used object against |
| 63 | +/// [/datum/cooking/recipe_step/proc/check_conditions_met]. if we meet the |
| 64 | +/// conditions, we track the recipe and the step. |
| 65 | +/// * for each unique step type that we're tracking, call |
| 66 | +/// [/datum/cooking/recipe_step/proc/follow_step] on the first instance of |
| 67 | +/// that step type, then [/datum/cooking/recipe_step/proc/is_complete] on |
| 68 | +/// all recipe step instances of that type, to see if we advance their |
| 69 | +/// respective recipes. |
| 70 | +/// |
| 71 | +/// Once a recipe reaches its final step, the tracker completes the recipe and |
| 72 | +/// typically stops existing at that point. |
55 | 73 | /datum/cooking/recipe_tracker/proc/process_item(mob/user, obj/used) |
56 | 74 | // TODO: I *hate* passing in a user here and want to move all the necessary |
57 | 75 | // UI interactions (selecting which recipe to complete, selecting which step |
|
61 | 79 | var/list/completed_recipes = list() |
62 | 80 | var/list/silent_recipes = list() |
63 | 81 | var/list/attempted_step_per_recipe = list() |
64 | | - var/datum/cooking/recipe_step/use_step_type |
65 | | - |
66 | 82 |
|
67 | 83 | for(var/datum/cooking/recipe/recipe in recipes_last_completed_step) |
68 | 84 | var/current_idx = recipes_last_completed_step[recipe] |
|
73 | 89 | next_step = recipe.steps[++current_idx] |
74 | 90 | var/conditions = next_step.check_conditions_met(used, src) |
75 | 91 | if(conditions == PCWJ_CHECK_VALID) |
76 | | - LAZYADD(valid_steps[next_step], next_step) |
| 92 | + LAZYADD(valid_steps[next_step.type], next_step) |
77 | 93 | LAZYADD(valid_recipes[next_step.type], recipe) |
78 | 94 | attempted_step_per_recipe[recipe] = current_idx |
79 | | - if(!use_step_type) |
80 | | - use_step_type = next_step.type |
81 | 95 | match = TRUE |
82 | 96 | break |
83 | 97 | else if(conditions == PCWJ_CHECK_SILENT) |
|
94 | 108 | return PCWJ_PARTIAL_SUCCESS |
95 | 109 | return PCWJ_NO_STEPS |
96 | 110 |
|
97 | | - var/datum/cooking/recipe_step/sample_step = valid_steps[1] |
98 | | - var/step_data = sample_step.follow_step(used, src) |
99 | | - step_reaction_message = step_data["message"] |
| 111 | + var/list/recipes_with_completed_steps = list() |
| 112 | + var/list/step_data |
100 | 113 | var/complete_steps = 0 |
101 | | - for(var/i in 1 to length(valid_recipes[use_step_type])) |
102 | | - var/datum/cooking/recipe/recipe = valid_recipes[use_step_type][i] |
103 | | - var/datum/cooking/recipe_step/recipe_step = valid_steps[i] |
104 | | - if(recipe_step.is_complete(used, src, step_data)) |
105 | | - recipes_last_completed_step[recipe] = attempted_step_per_recipe[recipe] |
106 | | - complete_steps++ |
| 114 | + for(var/step_type in valid_steps) |
| 115 | + // For each valid step type we only call follow_step() once since it's |
| 116 | + // pointless to e.g. add an item to the container more than once. |
| 117 | + // |
| 118 | + // However, we are still calling follow_step more than once. which means |
| 119 | + // we have to deal with the possibility that two valid steps may do two |
| 120 | + // different things with the used item and may expect different results. |
| 121 | + // Sojurn tried to handle this by adding a user prompt at this point, |
| 122 | + // asking which step the player wanted to perform. I want to avoid |
| 123 | + // throwing up interfaces during cooking, especially when unexpected, so |
| 124 | + // for now, we do nothing, and just watch out for situations where two |
| 125 | + // different recipe steps with incompatible end states are valid with |
| 126 | + // the same object. |
| 127 | + var/datum/cooking/recipe_step/sample_step = valid_steps[step_type][1] |
| 128 | + step_data = sample_step.follow_step(used, src) |
| 129 | + step_reaction_message = step_data["message"] |
| 130 | + |
| 131 | + for(var/i in 1 to length(valid_recipes[step_type])) |
| 132 | + var/datum/cooking/recipe/recipe = valid_recipes[step_type][i] |
| 133 | + var/datum/cooking/recipe_step/recipe_step = valid_steps[step_type][i] |
| 134 | + if(recipe_step.is_complete(used, src, step_data)) |
| 135 | + recipes_last_completed_step[recipe] = attempted_step_per_recipe[recipe] |
| 136 | + recipes_with_completed_steps |= recipe |
| 137 | + complete_steps++ |
107 | 138 |
|
108 | 139 | var/obj/item/reagent_containers/cooking/container = locateUID(container_uid) |
109 | 140 | if(complete_steps) |
|
121 | 152 | else |
122 | 153 | return PCWJ_PARTIAL_SUCCESS |
123 | 154 |
|
124 | | - for(var/datum/cooking/recipe in recipes_last_completed_step) |
125 | | - if(!(recipe in valid_recipes[sample_step.type])) |
| 155 | + for(var/recipe in recipes_last_completed_step) |
| 156 | + if(!(recipe in recipes_with_completed_steps)) |
126 | 157 | recipes_last_completed_step -= recipe |
127 | 158 |
|
128 | 159 | var/datum/cooking/recipe/recipe_to_complete |
|
0 commit comments