--- scripts/core/quests_check.gd +++ scripts/core/quests_check.gd @@ -137,6 +137,8 @@ hero.clear_held_dish(second) second.queue_free() + await _cooked_dish_questions(room) + # Le journal de la console. var menu: RecipeMenu = room.recipe_menu menu.process_mode = Node.PROCESS_MODE_ALWAYS @@ -190,6 +192,100 @@ "the end of a dive does not reset only the quests that last one dive") await _finish() +# Finish through the real stove update while the player tends the station. +func _cook_question_meal(room: Node, recipe_id: String = MEAL) -> Dish: + for ingredient_id: String in DataCatalog.RECIPES[recipe_id].ingredients: + GameState.add_ingredient(ingredient_id, int(DataCatalog.RECIPES[recipe_id].ingredients[ingredient_id])) + room.start_cooking(recipe_id, 0) + check(room.station_is_busy(0), "the question's meal did not start cooking") + room.stations[0].remaining = 0.01 + room.player.controls_enabled = true + room.player.global_position = room.cooking_station.default_stand_position() + room.player.refresh_target() + Input.action_press("action") + room._process(0.1) + Input.action_release("action") + await _frames(2) + check(not room.station_is_busy(0), "tending the stove did not finish the meal") + for node: Node in GameState.scoped_nodes(room, "dish"): + if node is Dish and node.recipe_id == recipe_id and node.state == Dish.State.FILLED and not node.is_queued_for_deletion(): + return node as Dish + check(false, "the finished meal is missing") + return null + +func _cooked_dish_questions(room: Node) -> void: + GameState.set_key_item_amount(TOKEN, 0) + var dish := await _cook_question_meal(room, OTHER) + check(room.get_node_or_null("ConfirmPrompt") == null and not get_tree().paused, "an unrelated meal opens a quest question") + if is_instance_valid(dish): + dish.free() + GameState.set_quest_value(QUEST, "state", 2) + dish = await _cook_question_meal(room) + check(room.get_node_or_null("ConfirmPrompt") == null, "a completed quest opens a meal question") + if is_instance_valid(dish): + dish.free() + GameState.set_quest_value(QUEST, "state", 1) + GameState.set_key_item_amount(TOKEN, 1) + dish = await _cook_question_meal(room) + check(room.get_node_or_null("ConfirmPrompt") == null, "a full quest bag opens a meal question") + if is_instance_valid(dish): + dish.free() + GameState.set_key_item_amount(TOKEN, 0) + # No giver configured: name the quest, and let the player decline. + dish = await _cook_question_meal(room) + var prompt := room.get_node_or_null("ConfirmPrompt") + check(prompt != null and get_tree().paused, "finishing a wanted dish opens no question") + if prompt == null: + if is_instance_valid(dish): + dish.free() + return + check(prompt.question == Loc.ui("ui.prompt.set_aside") % "Probe errand", "the meal question does not name its quest") + prompt.cancel_button.pressed.emit() + await _frames(3) + check(not get_tree().paused and is_instance_valid(dish) and dish.state == Dish.State.FILLED and GameState.key_item_amount(TOKEN) == 0, + "declining consumes the plate, gives an item, or leaves the game paused") + check(room.get_node_or_null("ConfirmPrompt") == null, "a declined portion immediately asks again") + dish.free() + # A different giver's presence blocks the prompt, including while leaving. + DataCatalog.QUESTS[QUEST].giver = VIP_CHARACTER + var giver: Customer = CustomerScene.instantiate() + room.add_child(giver) + giver.setup(VIP, room, -1, -1, Vector2.ZERO, room.entrance_point()) + room.customers.append(giver) + giver.state = Customer.State.LEAVING + dish = await _cook_question_meal(room) + check(room.get_node_or_null("ConfirmPrompt") == null and not get_tree().paused, + "a giver still at the restaurant opens a take-away question") + if is_instance_valid(dish): + dish.free() + room.customers.erase(giver) + giver.free() + dish = await _cook_question_meal(room) + prompt = room.get_node_or_null("ConfirmPrompt") + check(prompt != null and get_tree().paused, "an absent giver opens no meal question") + if prompt != null: + check(prompt.question == Loc.ui("ui.prompt.set_aside") % "Madame Probe", "the meal question does not name its giver") + prompt.confirm_button.pressed.emit() + prompt.confirm_button.pressed.emit() + await _frames(2) + check(GameState.key_item_amount(TOKEN) == 1 and not is_instance_valid(dish) and not get_tree().paused, + "confirming does not put exactly one meal in the bag and release the plate") + # Cooking offstage must not interrupt the current scene; offer on return. + GameState.set_key_item_amount(TOKEN, 0) + GameState.park_restaurant(room) + dish = await _cook_question_meal(room) + check(room.get_node_or_null("ConfirmPrompt") == null and not get_tree().paused, "offstage cooking pauses the active scene") + GameState.restore_offstage_restaurant() + room._process(0.0) + await _frames(2) + prompt = room.get_node_or_null("ConfirmPrompt") + check(prompt != null, "a still-ready quest portion is not offered on return") + if prompt != null: + prompt.confirm_button.pressed.emit() + await _frames(2) + check(GameState.key_item_amount(TOKEN) == 1 and not get_tree().paused, "the returned meal did not enter the quest bag") + DataCatalog.QUESTS[QUEST].giver = "" + func _finish() -> void: GameState.key_items.clear() GameState.release_offstage_restaurant()