2025-05-19 22:49:38 +08:00

292 lines
12 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.

extends UIPage
# --- UI 节点引用 ---
@onready var title_label: Label = $BG/Title/Title
@onready var npc_name_label: Label = $BG/Option/NPC_Info_1/Name
@onready var npc_staff_type_label: Label = $BG/Option/NPC_Info_1/Staff # 通常显示 "员工"
@onready var npc_job_label: Label = $BG/Option/NPC_Info_2/Info_List_0/Job/Title
@onready var npc_level_label: Label = $BG/Option/NPC_Info_2/Info_List_0/Job/Level
@onready var npc_icon_rect: TextureRect = $BG/Option/NPC_Info_2/Info_List_0/Icon
@onready var stat_design_label: Label = $BG/Option/NPC_Info_2/Info_List_1/Info_1/info
@onready var stat_code_label: Label = $BG/Option/NPC_Info_2/Info_List_1/Info_2/info
@onready var stat_art_label: Label = $BG/Option/NPC_Info_2/Info_List_1/Info_3/info
@onready var stat_audio_label: Label = $BG/Option/NPC_Info_2/Info_List_1/Info_4/info
@onready var cost_label: Label = $BG/Option/NPC_Info_2/Info_List_3/info_4/info
@onready var power_bar_segments_container: HBoxContainer = $BG/Option/NPC_Info_2/Info_List_2
var _power_bar_segments: Array[ColorRect] = [] # 用于存储体力条的各个片段
@onready var prev_button: Button = $BG/Title/previous/Button
@onready var next_button: Button = $BG/Title/next/Button
@onready var confirm_button: Button = $BG/Confirm
@onready var notice_path: Control = $notice
@export var Suitable_position:Array = []
# --- 内部状态 ---
var _all_npcs_data: Dictionary = {} # 存储从 GameState 加载的所有NPC原始数据
var enabled_npc_keys: Array[String] = [] # 存储所有当前可选的NPC的键 (名字)
var current_npc_index: int = -1 # 当前在 enabled_npc_keys 数组中选中的NPC的索引
var temp_next_ui_node_path = ''
# --- 常量 ---
const NPC_ICON_BASE_PATH = "res://Entity/NPC/art/" # NPC 图标的基础路径 (如果后续有 Icon 字段)
const DEFAULT_NPC_ICON_PATH = "res://Entity/NPC/art/秘书.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:
super._ready()
var node_name = str(self.name)
add_to_group(node_name) # 方便父节点或其他系统查找
temp_next_ui_node_path = next_ui_node_path
# 收集体力条的片段
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.duplicate(true)
# Suitable_position 是一个 @export var Array你需要确保它在编辑器中或通过代码被正确赋值。
# 例如: Suitable_position = ["项目经理", "技术总监", "艺术总监"]
for npc_key in _all_npcs_data:
var npc_info = _all_npcs_data[npc_key]
if typeof(npc_info) == TYPE_DICTIONARY:
var npc_type: String = npc_info.get("type", "") # 获取NPC类型默认为空字符串
var npc_title: String = npc_info.get("title", "") # 获取NPC职位默认为空字符串
var npc_outsourcing: float = float(npc_info.get("outsourcing", 0.0)) # 获取外包费用默认为0.0
# 检查条件1: type是员工同时title在Suitable_position中有
var condition1_met = false
if npc_type == "员工" and Suitable_position.has(npc_title):
condition1_met = true
# 检查条件2: outsourcing>0同时title在Suitable_position中有
var condition2_met = false
if npc_outsourcing > 0.0 and Suitable_position.has(npc_title): # 浮点数比较建议与 0.0 比较
condition2_met = true
# 如果任一条件满足则将该NPC加入到可用列表中
if condition1_met or condition2_met:
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]
# 从 cost_label 获取费用文本并转换为整数
var cost_string = cost_label.text
var current_npc_cost: int
# 进行转换,并处理可能的转换失败 (尽管在此逻辑下cost_label.text 应该总是数字)
if cost_string.is_valid_int():
current_npc_cost = cost_string.to_int()
else:
printerr(str(self.name) + ": Error converting cost_label.text ('" + cost_string + "') to integer.")
# 可以选择在这里弹出一个错误提示给用户,或者阻止后续操作
# 例如,可以简单地返回,或者显示一个通知
go_to_child_page(notice_path) # 假设 notice_path 可以显示一个通用错误
return
# 导航到下一个页面或结束工作流
next_ui_node_path = temp_next_ui_node_path
# 将 GameState 中的 money 与当前NPC的 cost 进行比较
if GameState.get_value("money") < current_npc_cost:
# 如果钱不够,跳转到提示页面 (例如,显示“资金不足”)
# 您可能需要一个特定的提示页面或消息来指明是费用不足
# GameState.set_value("notice_msg","资金不足以支付该负责人费用:" + str(current_npc_cost)) # 示例:设置特定提示信息
go_to_child_page(notice_path)
else:
# 如果钱足够,则扣除费用
var new_money = GameState.get_value("money") - current_npc_cost
GameState.set_value("money", new_money)
# 设置选中的NPC为关键环节负责人
set_main_data("关键环节负责人", selected_npc_key)
GameState.set_value("dialogue_npc", selected_npc_key)
#设置任务状态开启
GameState.set_value("is_on_task",true)
go_next() # 进入下一个UI流程