Tales-of-PKMN/game/quest_journal/quest_journal.gd

155 lines
5.2 KiB
GDScript

extends Control
class_name QuestJournal
enum Tab { MAIN, SIDE, COMPLETED }
const QUEST_ENTRY_SCENE := preload("res://game/quest_journal/quest_entry.tscn")
const OBJECTIVE_ROW_SCENE := preload("res://game/quest_journal/objective_row.tscn")
const REWARD_ROW_SCENE := preload("res://game/quest_journal/reward_row.tscn")
@onready var tab_bar: TabBar = $MarginContainer/HBoxContainer/LeftPanel/TabBar
@onready var quest_list: VBoxContainer = $MarginContainer/HBoxContainer/LeftPanel/ScrollContainer/QuestList
@onready var footer_label: Label = $MarginContainer/HBoxContainer/LeftPanel/FooterLabel
@onready var detail_title: Label = $MarginContainer/HBoxContainer/RightPanel/DetailScroll/DetailContent/DetailTitle
@onready var detail_category: Label = $MarginContainer/HBoxContainer/RightPanel/DetailScroll/DetailContent/DetailCategory
@onready var detail_description: RichTextLabel = $MarginContainer/HBoxContainer/RightPanel/DetailScroll/DetailContent/DetailDescription
@onready var objectives_list: VBoxContainer = $MarginContainer/HBoxContainer/RightPanel/DetailScroll/DetailContent/ObjectivesList
@onready var rewards_list: VBoxContainer = $MarginContainer/HBoxContainer/RightPanel/DetailScroll/DetailContent/RewardsList
var _current_tab: Tab = Tab.MAIN
var _selected_quest_id: StringName = &""
func _ready() -> void:
tab_bar.tab_changed.connect(_on_tab_changed)
GameEvents.quest_started.connect(_on_quest_changed)
GameEvents.quest_completed.connect(_on_quest_changed)
GameEvents.quest_objective_updated.connect(_on_objective_updated)
refresh()
func _on_tab_changed(index: int) -> void:
_current_tab = index as Tab
refresh()
func _on_quest_changed(_id: StringName) -> void:
refresh()
func _on_objective_updated(_qid: StringName, _idx: int, _cur: int, _req: int) -> void:
refresh() # simple et suffisant
# --- Rafraîchissement global ---
func refresh() -> void:
_clear_list()
var quests := _get_quests_for_tab(_current_tab)
if quests.is_empty():
_show_empty_state()
_clear_detail()
return
# Tri : principales par chapter_index, secondaires par titre
if _current_tab == Tab.MAIN:
quests.sort_custom(func(a, b): return a.chapter_index < b.chapter_index)
else:
quests.sort_custom(func(a, b): return a.title < b.title)
for quest in quests:
var entry := QUEST_ENTRY_SCENE.instantiate()
entry.setup(quest, _current_tab == Tab.COMPLETED)
entry.quest_selected.connect(_on_quest_selected)
quest_list.add_child(entry)
# Auto-sélection : garde la sélection actuelle si elle est toujours valide
var still_valid := quests.any(func(q): return q.quest_id == _selected_quest_id)
if still_valid:
_on_quest_selected(_selected_quest_id)
elif quests.size() > 0:
_on_quest_selected(quests[0].quest_id)
else:
_clear_detail()
_update_footer()
func _get_quests_for_tab(tab: Tab) -> Array[QuestData]:
var result: Array[QuestData] = []
match tab:
Tab.MAIN:
for q in QuestManager.active_quests.values():
if q.category == QuestData.Category.MAIN:
result.append(q)
Tab.SIDE:
for q in QuestManager.active_quests.values():
if q.category == QuestData.Category.SIDE:
result.append(q)
Tab.COMPLETED:
for q in QuestManager.completed_quests.values():
result.append(q)
return result
func _clear_list() -> void:
for child in quest_list.get_children():
child.queue_free()
func _show_empty_state() -> void:
var label := Label.new()
label.text = "Aucune quête dans cette catégorie."
label.add_theme_color_override("font_color", Color(0.6, 0.6, 0.6))
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
quest_list.add_child(label)
func _update_footer() -> void:
var main_count := 0
var side_count := 0
for q in QuestManager.active_quests.values():
if q.category == QuestData.Category.MAIN: main_count += 1
elif q.category == QuestData.Category.SIDE: side_count += 1
footer_label.text = "Principales : %d | Secondaires : %d | Terminées : %d" % [
main_count, side_count, QuestManager.completed_quests.size()
]
# --- Détail d'une quête ---
func _on_quest_selected(quest_id: StringName) -> void:
_selected_quest_id = quest_id
var quest: QuestData = QuestManager.all_quests.get(quest_id)
if quest == null:
_clear_detail()
return
detail_title.text = quest.title
detail_category.text = _category_label(quest.category)
detail_description.text = quest.description
# Objectifs
for child in objectives_list.get_children():
child.queue_free()
for obj in quest.objectives:
var row := OBJECTIVE_ROW_SCENE.instantiate()
row.setup(obj, _current_tab == Tab.COMPLETED)
objectives_list.add_child(row)
# Récompenses
for child in rewards_list.get_children():
child.queue_free()
for reward in quest.rewards:
var row := REWARD_ROW_SCENE.instantiate()
row.setup(reward)
rewards_list.add_child(row)
func _clear_detail() -> void:
detail_title.text = ""
detail_category.text = ""
detail_description.text = ""
for child in objectives_list.get_children():
child.queue_free()
for child in rewards_list.get_children():
child.queue_free()
func _category_label(cat: QuestData.Category) -> String:
match cat:
QuestData.Category.MAIN: return "QUÊTE PRINCIPALE"
QuestData.Category.SIDE: return "QUÊTE SECONDAIRE"
QuestData.Category.HIDDEN: return "QUÊTE SECRÈTE"
return ""