diff --git a/adventurer.gd b/adventurer.gd index 1b48c58..c2f3365 100644 --- a/adventurer.gd +++ b/adventurer.gd @@ -1,7 +1,5 @@ class_name Adventurer extends Npc - - func _ready() -> void: nav_agent.navigation_finished.connect(_on_nav_agent_finished) pass diff --git a/ai/tasks/actions/use_guild_equipment.gd b/ai/tasks/actions/use_guild_equipment.gd new file mode 100644 index 0000000..ac2f8c8 --- /dev/null +++ b/ai/tasks/actions/use_guild_equipment.gd @@ -0,0 +1,109 @@ +#* +#* use_guild_equipment.gd +#* +@tool +extends BTAction +## Moves the agent to the specified position, favoring horizontal movement. [br] +## Returns [code]SUCCESS[/code] when close to the target position (see [member tolerance]); +## otherwise returns [code]RUNNING[/code]. + + +enum Phases { + ARRIVE, + QUEUE, + WAIT, + SERVICE, + COMPLETE +} + +## Blackboard variable that stores the target position (Vector2) +@export var equipment_name : String = "" + +## Variable that stores desired speed (float) +@export var service_name : String = "" + +var equipment : Interactable +var queue : GuildQueue +var wait_time_remaining : float = 0 +var phase : Phases + + +func _generate_name() -> String: + return "Use Guild Equipment (%s) - %s" % [ + equipment_name, + service_name + ] + +func _enter() -> void: + var eq = Guild.hall.interactables.get(equipment_name) + if !eq: + printerr("Use Guild Equipment (%s) - %s, '%s' not found!", equipment_name, service_name, equipment_name) + return + equipment = eq + queue = equipment.queue + phase = Phases.ARRIVE + queue.add_member(agent) + agent.approach(queue.get_last_position()) + agent.navigation_finished.connect(_on_navigation_complete) + agent.navigation_failed.connect(_on_navigation_failed) + +func _tick(delta: float) -> Status: + if equipment == null: + return FAILURE + match(phase): + Phases.ARRIVE: + if wait_time_remaining > 0: + wait_time_remaining -= delta + if wait_time_remaining <= 0: + agent.navigation_finished.connect(_on_navigation_complete) + agent.approach(queue.get_member_position(agent)) + Phases.QUEUE: + pass + Phases.WAIT: + pass + Phases.SERVICE: + if wait_time_remaining > 0: + wait_time_remaining -= delta + if wait_time_remaining <= 0: + equipment.service_provided.connect(_on_service_complete) + equipment.interact(agent, service_name) + Phases.COMPLETE: + return SUCCESS + return RUNNING + +func _on_navigation_complete() -> void: + agent.navigation_finished.disconnect(_on_navigation_complete) + agent.navigation_failed.disconnect(_on_navigation_failed) + queue.advanced.connect(_on_queue_advanced) + phase = Phases.QUEUE + +func _on_navigation_failed() -> void: + wait_time_remaining = randf_range(.5, 2) + agent.navigation_finished.disconnect(_on_navigation_complete) + +func use_service(): + phase = Phases.SERVICE + wait_time_remaining = randf_range(2,5) + #TODO: Make them both do the talking emoji + agent.show_speech_bubble("busy") + +func wait(): + wait_time_remaining = 1 + phase = Phases.WAIT + + +func _on_queue_advanced() -> void: + if queue.front == agent: + queue.advanced.disconnect(_on_queue_advanced) + if equipment.busy: + wait() + else: + use_service() + pass + +func _on_service_complete() -> void: + equipment.service_provided.disconnect(_on_service_complete) + agent.show_speech_bubble("") + queue.remove_member(agent) + phase = Phases.COMPLETE + diff --git a/ai/tasks/actions/use_guild_equipment.gd.uid b/ai/tasks/actions/use_guild_equipment.gd.uid new file mode 100644 index 0000000..45d63c0 --- /dev/null +++ b/ai/tasks/actions/use_guild_equipment.gd.uid @@ -0,0 +1 @@ +uid://bhatmue8jr2ab diff --git a/guildhall.gd b/guildhall.gd index b96be44..519a935 100644 --- a/guildhall.gd +++ b/guildhall.gd @@ -1,6 +1,7 @@ class_name Guildhall extends Node2D var employees : Dictionary[String, GuildEmployee] = {} +var interactables : Dictionary[String, Interactable] = {} var board : QuestBoard @onready var sprite_node : Node2D = $Sprites @onready var nav_region : NavigationRegion2D = $RoomRegion @@ -14,7 +15,9 @@ func _ready() -> void: func register_employee(employee: GuildEmployee) -> void: employees[employee.name] = employee - + +func register_interactables(equipment: Interactable) -> void: + interactables[equipment.name] = equipment func add_sprite(sprite : Adventurer) -> void: sprite_node.add_child(sprite) diff --git a/guildhall.tscn b/guildhall.tscn index 0b0476c..63519e9 100644 --- a/guildhall.tscn +++ b/guildhall.tscn @@ -7,7 +7,6 @@ [ext_resource type="Texture2D" uid="uid://cg6ptmynq0aq0" path="res://basic-sprite.png" id="4_l3mu1"] [ext_resource type="PackedScene" uid="uid://cf6nnjyp8kv78" path="res://receptionist.tscn" id="5_l3mu1"] [ext_resource type="Texture2D" uid="uid://bnt2dlv7kxw7s" path="res://questboard.png" id="6_2wofw"] -[ext_resource type="Script" uid="uid://blo7tb5135vfm" path="res://quest_board.gd" id="7_bog1h"] [ext_resource type="Script" uid="uid://b0q2233msdtgo" path="res://guild_queue.gd" id="7_hph4e"] [ext_resource type="PackedScene" uid="uid://drrtypncppjps" path="res://quest_board_window.tscn" id="8_uo85v"] @@ -27,6 +26,18 @@ vertices = PackedVector2Array(117.96875, 286, 9.96875, 286, 9.03125, 0, 117.0312 polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)]) outlines = Array[PackedVector2Array]([PackedVector2Array(-1, -10, 127, -10, 128, 296, 0, 296)]) +[sub_resource type="GDScript" id="GDScript_bog1h"] +script/source = "class_name QuestBoard extends Interactable + +signal service_provided() + +func _ready() -> void: + queue = $Queue + +func interact(interactor, service : String): + service_provided.emit() +" + [node name="Guildhall" type="Node2D"] script = ExtResource("1_lsinl") @@ -83,7 +94,7 @@ navigation_polygon = SubResource("NavigationPolygon_l3mu1") [node name="Quest Board" type="StaticBody2D" parent="."] position = Vector2(935, 32) -script = ExtResource("7_bog1h") +script = SubResource("GDScript_bog1h") [node name="QuestBoardWindow" parent="Quest Board" instance=ExtResource("8_uo85v")] diff --git a/interactable.gd b/interactable.gd index 6282810..77639ca 100644 --- a/interactable.gd +++ b/interactable.gd @@ -1 +1,12 @@ class_name Interactable extends StaticBody2D + +var busy : bool = false +var queue : GuildQueue + +signal service_provided() + +func _ready() -> void: + queue = $Queue + +func interact(interactor, service : String = ""): + service_provided.emit() diff --git a/main_panel.gd b/main_panel.gd index eb57389..24de89b 100644 --- a/main_panel.gd +++ b/main_panel.gd @@ -16,7 +16,7 @@ func _process(delta: float) -> void: func add_quest_progress_bar(quest : Quest) -> void: var qpb : QuestProgressBar = quest_progress_bar_template.instantiate() qpb.setup(quest) - %QuestProgressList/VBoxContainer.add_child(qpb) + %QuestList.add_child(qpb) #TODO: Change the hero portrait to match if quest.steps > 1: for i in range(quest.steps-1): diff --git a/main_panel.tscn b/main_panel.tscn index c9cfcee..bf0f5a8 100644 --- a/main_panel.tscn +++ b/main_panel.tscn @@ -18,6 +18,7 @@ corner_radius_bottom_left = 3 corner_detail = 5 [node name="MainPanel" type="MarginContainer"] +anchors_preset = -1 offset_right = 319.0 offset_bottom = 189.0 theme_override_constants/margin_left = 0 @@ -36,7 +37,8 @@ custom_minimum_size = Vector2(260, 100) layout_mode = 2 horizontal_scroll_mode = 0 -[node name="VBoxContainer" type="VBoxContainer" parent="QuestProgressList"] +[node name="QuestList" type="VBoxContainer" parent="QuestProgressList"] +unique_name_in_owner = true custom_minimum_size = Vector2(300, 100) layout_mode = 2 diff --git a/quest_board.gd b/quest_board.gd index ef0b7e1..21cdda6 100644 --- a/quest_board.gd +++ b/quest_board.gd @@ -4,15 +4,13 @@ class_name QuestBoard extends Interactable @onready var polygon : CollisionPolygon2D = $CollisionPolygon2D @onready var window : QuestBoardWindow = $QuestBoardWindow -var busy : bool - signal interaction_complete() func _ready() -> void: register_board.call_deferred() func register_board() -> void: - Guild.hall.board = self + Guild.hall.register_interactables(self) func _input(event : InputEvent) -> void: var evt : InputEventMouseButton = event as InputEventMouseButton diff --git a/quest_board_entry.gd b/quest_board_entry.gd index c8be1d7..e4762fa 100644 --- a/quest_board_entry.gd +++ b/quest_board_entry.gd @@ -6,9 +6,11 @@ var quest : Quest = null @onready var tex_icon : TextureRect = %Icon @onready var name_label : Label = %NameLabel @onready var status_label : Label = %StatusLabel +var board_window : QuestBoardWindow = null func setup(quest : Quest) -> void: self.quest = quest + quest.status_changed.connect(_on_quest_status_changed) name_label.text = quest.name status_label.text = "Available" if !quest.taken else "Unavailable" @@ -16,9 +18,17 @@ func update() -> void: status_label.text = "Available" if !quest.taken else "Unavailable" +func _on_quest_status_changed(status: Quest.Status) -> void: + match(status): + Quest.Status.OPEN: status_label.text = "Available" + Quest.Status.TAKEN:queue_free() + Quest.Status.COMPLETED: queue_free() + _: status_label.text = "Unavailable" + func _on_pressed() -> void: var window = quest_window_template.instantiate() window.setup(quest, true) + window.quest_accepted.connect(board_window._on_quest_accepted) add_child(window) window.popup_centered() diff --git a/quest_board_entry.tscn b/quest_board_entry.tscn index 39bdf32..562e455 100644 --- a/quest_board_entry.tscn +++ b/quest_board_entry.tscn @@ -5,6 +5,7 @@ [node name="QuestBoardEntry" type="Button"] custom_minimum_size = Vector2(200, 50) +anchors_preset = -1 offset_right = 200.0 offset_bottom = 50.0 script = ExtResource("1_qfdrh") diff --git a/quest_board_window.gd b/quest_board_window.gd index 4608c78..4f8b4ce 100644 --- a/quest_board_window.gd +++ b/quest_board_window.gd @@ -3,22 +3,23 @@ class_name QuestBoardWindow extends Popup const entry_template = preload("res://quest_board_entry.tscn") @onready var entry_list : VBoxContainer = %Entries -var entries : Array[QuestBoardEntry] = [] + func populate(quests : Array[Quest]) -> void: - for entry in entries: + for entry : QuestBoardEntry in entry_list.get_children(): entry.queue_free() - entries.clear() for quest in quests: if !quest.taken: add_entry(quest) func add_entry(quest : Quest) -> void: var qle : QuestBoardEntry = entry_template.instantiate() - entries.append(qle) entry_list.add_child(qle) qle.setup(quest) + qle.board_window = self +func _on_quest_accepted() -> void: + hide() func _on_close_requested() -> void: hide() diff --git a/quest_log_entry.gd b/quest_log_entry.gd index 7a49c65..810e278 100644 --- a/quest_log_entry.gd +++ b/quest_log_entry.gd @@ -15,4 +15,7 @@ func update() -> void: status_label.text = "Available" if !quest.taken else "Unavailable" func _on_quest_status_changed(status : Quest.Status) -> void: - update() + match(status): + Quest.Status.OPEN: status_label.text = "Available" + Quest.Status.COMPLETED: queue_free() + _: status_label.text = "Unavailable" diff --git a/quest_panel_entry.gd b/quest_panel_entry.gd index 62c8ae3..2bfcb01 100644 --- a/quest_panel_entry.gd +++ b/quest_panel_entry.gd @@ -9,7 +9,7 @@ var enabled: bool: enable(value) var quest : Quest - +@onready var status_label = %StatusLabel func enable(en: bool) -> void: _enabled = en @@ -20,6 +20,7 @@ func enable(en: bool) -> void: func setup(qst : Quest) -> void: quest = qst + quest.status_changed.connect(_on_quest_status_changed) %NameLabel.text = quest.name #TODO: Add star rating #%LevelLabel.text = str(data.level) @@ -30,3 +31,10 @@ func _on_gui_input(event: InputEvent) -> void: var evt = event as InputEventMouseButton if evt and evt.button_index == MOUSE_BUTTON_LEFT and evt.pressed: print("Quest clicked!") + +func _on_quest_status_changed(status: Quest.Status) -> void: + match(status): + Quest.Status.OPEN: status_label.text = "OPEN" + Quest.Status.COMPLETED: queue_free() + Quest.Status.IN_PROGRESS: status_label.text = "IN PROGRESS" + _: status_label.text = "Taken" diff --git a/quest_window.gd b/quest_window.gd index f2d9fe8..8d2ef28 100644 --- a/quest_window.gd +++ b/quest_window.gd @@ -1,6 +1,7 @@ extends Window var quest : Quest +signal quest_accepted() func setup(qst : Quest, board : bool) -> void: quest = qst @@ -31,6 +32,8 @@ func _on_quest_status_changed(status : Quest.Status) -> void: func _on_accept_pressed() -> void: Guild.assign_quest(Game.player.data, quest) + quest_accepted.emit() + queue_free() func _on_close_button_pressed() -> void: queue_free()