extends CanvasLayer class_name Tutorial const STEP_SCENE = preload("res://gui/game/tutorial/step_gui/step_gui.tscn") signal succeded var indicators: Array[InGameIndicator] var player: Player var region: Region var game_gui: GameGui var success = false @onready var steps: Array[Step] = [ Step.new( tr("MOVE_WITH_RIGHT_CLICK_OR_WASD").format({ "W": get_action_key_name("move_up"), "A": get_action_key_name("move_left"), "S": get_action_key_name("move_down"), "D": get_action_key_name("move_right") }), (func(): return player.global_position.distance_to(region.data.player_spawn) > 30) ), Step.new( tr("CHANGE_ZOOM_WITH_Z_X").format({ "Z": get_action_key_name("zoom_in"), "X": get_action_key_name("zoom_out") }), (func(): return GameInfo.settings_data.zoom != 1.), (func(): GameInfo.game_data.player_data.inventory.add_item(Detector.new())) ), Step.new( "SELECT_ITEM_WITH_SCROLL_CLICK_OR_NUMBER", (func(): return player.data.inventory.current_item_ind != player.data.inventory.tools.size()) ), Step.new( "LEFT_CLICK_TO_USE_ITEMS", (func (): return player.instruction is Player.ItemActionInstruction) ), Step.new( "USE_YOUR_DETECTOR_TO_FIND_THE_BATTERY", (func(): return player.position.distance_to(Vector2.ZERO) < 600) ), Step.new( "RECHARGE_IN_THE_RECHARGE_STATION", (func(): return region and region.data and not region.data.in_passing_day_animation and region.data.day != 1), (func(): game_gui.show_energy() game_gui.show_help() game_gui.help.display_energy_tutorial() await game_gui.help.tutorial_passed GameInfo.game_data.player_data.inventory.add_item(Pickaxe.new())) ), Step.new( "DIG_A_TALION_VEIN_WITH_SHOVEL", (func(): for e in region.entity_container.get_children(): if e is ItemObject and e.item is Seed: return true return false) ), Step.new( "TAKE_A_SEED_BY_CLICKING_ON_IT", (func(): return player.data.inventory.seeds.find_custom( func(i: Item): return i is Seed ) != -1) ), Step.new( tr("DROP_SEED_WITH_KEY").format({ "Q": get_action_key_name("drop") }), (func(): return ( Input.is_action_pressed("drop")) ) ), Step.new( "PLANT_SEED_IN_FERTILE_ZONE", (func(): for e in region.entity_container.get_children(): if e is Plant: game_gui.help.display_plant_info_tutorial(e.card_info()) return true return false) ), Step.new( "WAIT_FOR_THE_PLANT_MATURATION", (func(): return region and region.data and not region.data.in_passing_day_animation and region.data.get_score() != 0), (func(): GameInfo.game_data.player_data.inventory.add_item(Fork.new())) ), Step.new( "HARVEST_A_MATURE_PLANT", (func(): for e in region.entity_container.get_children(): if e is Plant and e.harvested: return true return false) ), Step.new( "TAKE_HARVESTED_SEEDS", (func(): for s in player.data.inventory.seeds: if s is Seed and len(s.plant_mutations) > 0: game_gui.help.display_mutations_tutorial(s.card_info()) return true return false), (func(): await game_gui.help.tutorial_passed game_gui.show_progress_bar() game_gui.help.display_plant_point_tutorial()) ), Step.new( "HAVE_3_PLANT_POINTS_SIMULTANEOUSLY", (func(): return region.data.get_score() >= 3) ), ] func _ready(): setup_gui() show() game_gui.show_energy(false) game_gui.show_progress_bar(false) game_gui.show_help(false) func setup_gui(): for s in %Steps.get_children(): s.queue_free() for s in steps: var new_step = STEP_SCENE.instantiate() as TutorialStepGui new_step.suceeded = false new_step.text = s.get_text() %Steps.add_child(new_step) func _process(_d): if success: hide() elif region and region.data and not success: var all_success = true for i in len(steps): var step := steps[i] var step_gui := %Steps.get_children()[i] as TutorialStepGui step_gui.visible = i == 0 or steps[i - 1].succeeded if step_gui.visible: var old_succeeded = step.succeeded step.update_succeeded() if old_succeeded != step.succeeded: # Put a delay so two state don't collide return step_gui.suceeded = step.succeeded if not step.succeeded: game_gui.objective_text = step.text all_success = false if all_success: finish_tutorial() func finish_tutorial(): region.data.state = RegionData.State.SUCCEEDED region.data.update() succeded.emit() success = true SteamConnection.unlock_achievement(SteamConnection.ACH_FINISH_TUTORIAL) class Step: var text: String: get = get_text var is_step_over_callable: Callable var on_succeeded: Callable var succeeded = false func _init( _text: String = "", _is_step_over_callable: Callable = (func(): return false), _on_succeeded: Callable = (func(): return false) ): text = _text is_step_over_callable = _is_step_over_callable on_succeeded = _on_succeeded func get_text() -> String: return text func update_succeeded() -> bool: if not succeeded: succeeded = is_step_over_callable.call() if succeeded: on_succeeded.call() return succeeded func get_action_key_name(action_name: String) -> String: var events: Array[InputEvent] = InputMap.action_get_events(action_name) var saved_remapped_input = null var existing_remapped_id: int = GameInfo.settings_data.action_remapped.find(action_name) if existing_remapped_id != -1: saved_remapped_input = GameInfo.settings_data.input_remapped[existing_remapped_id] var event: InputEvent = null if saved_remapped_input: event = saved_remapped_input else: event = null if events.size() == 0 else events[0] var input_name: String = "UNASSIGNED" if event == null else event.as_text() if event is InputEventKey: var keycode = DisplayServer.keyboard_get_keycode_from_physical(event.physical_keycode) input_name = OS.get_keycode_string(keycode) return input_name