Player can take quests, Adventurers in progress.

This commit is contained in:
2025-08-06 22:31:36 -04:00
parent d705ed0496
commit 6bfbd4b70c
15 changed files with 175 additions and 16 deletions

View File

@@ -1,7 +1,5 @@
class_name Adventurer extends Npc
func _ready() -> void:
nav_agent.navigation_finished.connect(_on_nav_agent_finished)
pass

View File

@@ -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

View File

@@ -0,0 +1 @@
uid://bhatmue8jr2ab

View File

@@ -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)

View File

@@ -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")]

View File

@@ -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()

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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")

View File

@@ -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()

View File

@@ -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"

View File

@@ -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"

View File

@@ -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()