258 lines
10 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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