219 lines
6.9 KiB
GDScript
219 lines
6.9 KiB
GDScript
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
|