258 lines
10 KiB
GDScript
258 lines
10 KiB
GDScript
# proposal.gd
|
||
extends Control
|
||
|
||
# --- UI 节点引用 ---
|
||
@onready var title_label: Label = $proposal/Title/Title
|
||
@onready var npc_name_label: Label = $proposal/Option/NPC_Info_1/Name
|
||
@onready var npc_staff_type_label: Label = $proposal/Option/NPC_Info_1/Staff # 通常显示 "员工"
|
||
@onready var npc_job_label: Label = $proposal/Option/NPC_Info_2/Info_List_0/Job/Title
|
||
@onready var npc_level_label: Label = $proposal/Option/NPC_Info_2/Info_List_0/Job/Level
|
||
@onready var npc_icon_rect: TextureRect = $proposal/Option/NPC_Info_2/Info_List_0/Icon
|
||
|
||
@onready var stat_design_label: Label = $proposal/Option/NPC_Info_2/Info_List_1/Info_1/info
|
||
@onready var stat_code_label: Label = $proposal/Option/NPC_Info_2/Info_List_1/Info_2/info
|
||
@onready var stat_art_label: Label = $proposal/Option/NPC_Info_2/Info_List_1/Info_3/info
|
||
@onready var stat_audio_label: Label = $proposal/Option/NPC_Info_2/Info_List_1/Info_4/info
|
||
|
||
@onready var cost_label: Label = $proposal/Option/NPC_Info_2/Info_List_3/info_4/info
|
||
|
||
@onready var power_bar_segments_container: HBoxContainer = $proposal/Option/NPC_Info_2/Info_List_2
|
||
var _power_bar_segments: Array[ColorRect] = [] # 用于存储体力条的各个片段
|
||
|
||
@onready var prev_button: Button = $proposal/Title/previous/Button
|
||
@onready var next_button: Button = $proposal/Title/next/Button
|
||
@onready var confirm_button: Button = $proposal/Confirm
|
||
|
||
# --- 内部状态 ---
|
||
var _all_npcs_data: Dictionary = {} # 存储从 GameState 加载的所有NPC原始数据
|
||
var enabled_npc_keys: Array[String] = [] # 存储所有当前可选的NPC的键 (名字)
|
||
var current_npc_index: int = -1 # 当前在 enabled_npc_keys 数组中选中的NPC的索引
|
||
|
||
# --- 常量 ---
|
||
const NPC_ICON_BASE_PATH = "res://Entity/NPC/" # NPC 图标的基础路径 (如果后续有 Icon 字段)
|
||
const DEFAULT_NPC_ICON_PATH = "res://Entity/NPC/NPC_1_UI.png" # 默认/占位NPC图标
|
||
|
||
const POWER_CURRENT_COLOR = Color.GREEN_YELLOW # 当前体力颜色
|
||
const POWER_MAX_POTENTIAL_COLOR = Color(0.2, 0.4, 0.2, 0.8) # 最大潜力槽颜色 (稍暗的绿色)
|
||
const POWER_DISABLED_COLOR = Color(0.1, 0.1, 0.1, 0.3) # 体力条禁用/未达到部分的颜色
|
||
|
||
|
||
func _ready() -> void:
|
||
var node_name = str(self.name)
|
||
add_to_group(node_name) # 方便父节点或其他系统查找
|
||
|
||
# 收集体力条的片段
|
||
for child in power_bar_segments_container.get_children():
|
||
if child is ColorRect:
|
||
_power_bar_segments.append(child)
|
||
if _power_bar_segments.size() != 20:
|
||
printerr(node_name + ": Expected 20 power bar segments, found " + str(_power_bar_segments.size()))
|
||
|
||
|
||
# 连接信号
|
||
if prev_button and not prev_button.pressed.is_connected(_on_previous_pressed):
|
||
prev_button.pressed.connect(_on_previous_pressed)
|
||
if next_button and not next_button.pressed.is_connected(_on_next_pressed):
|
||
next_button.pressed.connect(_on_next_pressed)
|
||
if confirm_button and not confirm_button.pressed.is_connected(_on_confirm_pressed):
|
||
confirm_button.pressed.connect(_on_confirm_pressed)
|
||
|
||
if not is_connected("visibility_changed",Callable(self,"_on_visibility_changed")):
|
||
visibility_changed.connect(Callable(self,"_on_visibility_changed"))
|
||
|
||
# 如果节点在 _ready 时就可见,则立即刷新显示
|
||
if is_visible_in_tree():
|
||
reset_display()
|
||
|
||
|
||
func _on_visibility_changed() -> void:
|
||
if is_visible_in_tree():
|
||
reset_display()
|
||
|
||
|
||
# 重置显示状态,在窗口可见时调用
|
||
func reset_display() -> void:
|
||
print(str(self.name) + ": Resetting display state.")
|
||
_load_and_filter_npcs()
|
||
|
||
if enabled_npc_keys.is_empty():
|
||
current_npc_index = -1
|
||
print(str(self.name) + ": No enabled NPCs found.")
|
||
else:
|
||
current_npc_index = 0 # 默认显示第一个可用的NPC
|
||
print(str(self.name) + ": Found %d enabled NPCs. Defaulting to index 0." % enabled_npc_keys.size())
|
||
|
||
_display_current_npc()
|
||
|
||
|
||
# 从 GameState 加载NPC数据并筛选出可用的负责人
|
||
func _load_and_filter_npcs() -> void:
|
||
_all_npcs_data.clear()
|
||
enabled_npc_keys.clear()
|
||
|
||
if not GameState:
|
||
printerr(str(self.name) + ": GameState not available in _load_and_filter_npcs.")
|
||
return
|
||
|
||
var raw_npcs_data = GameState.get_value("npcs", {})
|
||
if raw_npcs_data.is_empty():
|
||
print(str(self.name) + ": 'npcs' data in GameState is empty or not found.")
|
||
return
|
||
|
||
_all_npcs_data = raw_npcs_data
|
||
|
||
for npc_key in _all_npcs_data:
|
||
var npc_info = _all_npcs_data[npc_key]
|
||
if typeof(npc_info) == TYPE_DICTIONARY and npc_info.get("type") == "员工":
|
||
enabled_npc_keys.append(npc_key)
|
||
|
||
# 可选:对 enabled_npc_keys进行排序,以确保显示顺序一致
|
||
# enabled_npc_keys.sort()
|
||
print(str(self.name) + ": Loaded and filtered NPCs. Enabled count: " + str(enabled_npc_keys.size()))
|
||
|
||
# 根据 current_npc_index 更新UI显示
|
||
func _display_current_npc() -> void:
|
||
if current_npc_index < 0 or current_npc_index >= enabled_npc_keys.size():
|
||
# --- 处理没有可用NPC或索引无效的情况 ---
|
||
title_label.text = "策划案负责人"
|
||
npc_name_label.text = "无可用负责人"
|
||
npc_staff_type_label.text = "-" # 通常显示 "员工"
|
||
npc_job_label.text = "-"
|
||
npc_level_label.text = "-"
|
||
npc_icon_rect.texture = null # 或者一个“无”的占位图
|
||
stat_design_label.text = "-"
|
||
stat_code_label.text = "-"
|
||
stat_art_label.text = "-"
|
||
stat_audio_label.text = "-"
|
||
cost_label.text = "-"
|
||
|
||
# 隐藏所有体力条片段
|
||
for segment in _power_bar_segments:
|
||
segment.visible = false
|
||
|
||
if prev_button: prev_button.disabled = true
|
||
if next_button: next_button.disabled = true
|
||
if confirm_button: confirm_button.disabled = true
|
||
return
|
||
|
||
# --- 如果有有效NPC ---
|
||
if prev_button: prev_button.disabled = enabled_npc_keys.size() <= 1
|
||
if next_button: next_button.disabled = enabled_npc_keys.size() <= 1
|
||
if confirm_button: confirm_button.disabled = false
|
||
|
||
var display_index = current_npc_index + 1
|
||
var total_count = enabled_npc_keys.size()
|
||
title_label.text = "策划案负责人 %d/%d" % [display_index, total_count]
|
||
|
||
var npc_key = enabled_npc_keys[current_npc_index]
|
||
if not _all_npcs_data.has(npc_key):
|
||
printerr(str(self.name) + ": Current NPC key '%s' not found in cached _all_npcs_data!" % npc_key)
|
||
# 显示错误状态,可以做得更友好
|
||
npc_name_label.text = "错误:数据丢失"
|
||
# 隐藏所有体力条片段
|
||
for segment in _power_bar_segments:
|
||
segment.visible = false
|
||
return
|
||
|
||
var npc_info = _all_npcs_data[npc_key]
|
||
|
||
# 更新基本信息
|
||
npc_name_label.text = npc_key
|
||
npc_staff_type_label.text = npc_info.get("type", "员工") # 根据筛选,这里应该是"员工"
|
||
npc_job_label.text = npc_info.get("title", "-")
|
||
npc_level_label.text = "Lv" + str(int(npc_info.get("level", 1)))
|
||
|
||
# 更新图标 (后续会从npc_info.Icon获取)
|
||
var icon_name_from_data = npc_info.get("Icon", "") # 假设后续会有这个字段
|
||
if not icon_name_from_data.is_empty():
|
||
var dynamic_icon_path = NPC_ICON_BASE_PATH + icon_name_from_data + ".png" # 假设文件名规则
|
||
if ResourceLoader.exists(dynamic_icon_path):
|
||
npc_icon_rect.texture = ResourceLoader.load(dynamic_icon_path)
|
||
else:
|
||
printerr(str(self.name) + ": Failed to load NPC icon: " + dynamic_icon_path + ". Falling back to default.")
|
||
npc_icon_rect.texture = ResourceLoader.load(DEFAULT_NPC_ICON_PATH)
|
||
else:
|
||
# print(str(self.name) + ": NPC icon name is empty for key '%s'. Using default." % npc_key)
|
||
npc_icon_rect.texture = ResourceLoader.load(DEFAULT_NPC_ICON_PATH)
|
||
|
||
|
||
# 更新能力值 (确保转换为整数显示)
|
||
stat_design_label.text = str(int(npc_info.get("design", 0.0)))
|
||
stat_code_label.text = str(int(npc_info.get("code", 0.0)))
|
||
stat_art_label.text = str(int(npc_info.get("art", 0.0)))
|
||
stat_audio_label.text = str(int(npc_info.get("audio", 0.0)))
|
||
|
||
# 更新费用
|
||
cost_label.text = str(int(npc_info.get("outsourcing", 0.0)))
|
||
|
||
# --- 更新体力条 (包含 visible 控制) ---
|
||
var power = float(npc_info.get("power", 0.0))
|
||
var power_max = float(npc_info.get("power_max", 0.0))
|
||
|
||
if power_max <= 0: # 防止除零错误或无效数据
|
||
for segment in _power_bar_segments:
|
||
segment.visible = false # 如果最大体力为0或无效,所有格段都不可见
|
||
else:
|
||
var total_visible_segments = floori(power_max / 10.0) # 根据 power_max 计算总共应显示的格数
|
||
var current_power_segments = floori(power / 10.0) # 当前体力对应的格数
|
||
|
||
# 确保 current_power_segments 不会超过 total_visible_segments (逻辑上 power 不应大于 power_max)
|
||
current_power_segments = mini(current_power_segments, total_visible_segments)
|
||
|
||
for i in range(_power_bar_segments.size()): # 遍历所有20个可能的格段
|
||
var segment = _power_bar_segments[i]
|
||
|
||
if i < total_visible_segments:
|
||
segment.visible = true # 此格段在NPC的最大体力范围内,设为可见
|
||
if i < current_power_segments:
|
||
segment.color = POWER_CURRENT_COLOR # 当前体力部分
|
||
else:
|
||
segment.color = POWER_MAX_POTENTIAL_COLOR # 最大潜力中未充满的部分
|
||
else:
|
||
segment.visible = false # 此格段超出NPC的最大体力范围,设为不可见
|
||
|
||
func _on_previous_pressed() -> void:
|
||
if enabled_npc_keys.size() > 1:
|
||
current_npc_index -= 1
|
||
if current_npc_index < 0:
|
||
current_npc_index = enabled_npc_keys.size() - 1
|
||
_display_current_npc()
|
||
|
||
func _on_next_pressed() -> void:
|
||
if enabled_npc_keys.size() > 1:
|
||
current_npc_index += 1
|
||
if current_npc_index >= enabled_npc_keys.size():
|
||
current_npc_index = 0
|
||
_display_current_npc()
|
||
|
||
func _on_confirm_pressed() -> void:
|
||
if current_npc_index != -1 and current_npc_index < enabled_npc_keys.size():
|
||
var selected_npc_key = enabled_npc_keys[current_npc_index]
|
||
var parent_node = get_parent()
|
||
|
||
if parent_node and parent_node.has_method("update_task_options"):
|
||
parent_node.update_task_options({"关键环节负责人": selected_npc_key})
|
||
print(str(self.name) + ": Confirmed NPC '%s'. Sent to parent." % selected_npc_key)
|
||
else:
|
||
printerr(str(self.name) + ": Parent node not found or missing 'update_task_options' method.")
|
||
|
||
# 无论父节点是否成功更新,都尝试继续后续流程
|
||
if parent_node and parent_node.has_method("start_task"):
|
||
parent_node.start_task()
|
||
else:
|
||
printerr(str(self.name) + ": Parent node not found or missing 'start_task' method.")
|
||
|
||
if parent_node and parent_node.has_method("close_all_popups"):
|
||
parent_node.close_all_popups()
|
||
else:
|
||
printerr(str(self.name) + ": Parent node not found or missing 'close_all_popups' method.")
|
||
self.hide() # Fallback hide
|
||
else:
|
||
print(str(self.name) + ": No valid NPC selected to confirm.")
|
||
# 即使没有有效选择,也尝试关闭(或提示用户)
|
||
var parent_node = get_parent()
|
||
if parent_node and parent_node.has_method("close_all_popups"):
|
||
parent_node.close_all_popups() # 或者只关闭自己并返回主界面
|
||
else:
|
||
self.hide()
|