2024-12-23 01:29:31 +00:00
|
|
|
|
extends Node
|
|
|
|
|
|
2024-12-30 13:19:10 +00:00
|
|
|
|
enum VIBE {
|
|
|
|
|
NORAML,
|
|
|
|
|
MYSTERY,
|
|
|
|
|
DANGEROUS,
|
|
|
|
|
TOUCHING,
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
@export var first_entered = true
|
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
2025-04-01 08:16:29 +00:00
|
|
|
|
func _ready():
|
|
|
|
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-26 13:11:38 +00:00
|
|
|
|
# get_tree().node_added.connect("_on_node_added")
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
#### Ground and Loader ####
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func get_ground_loader() -> GroundLoader:
|
|
|
|
|
return get_node_or_null("/root/Main/GroundLoader") as GroundLoader
|
|
|
|
|
|
2025-06-19 06:50:06 +00:00
|
|
|
|
# restart scene in debug launch...
|
|
|
|
|
func is_restarting() -> bool:
|
|
|
|
|
var ground = get_ground()
|
|
|
|
|
if ground:
|
|
|
|
|
return ground.restarting
|
|
|
|
|
return false
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
|
func get_ground() -> Ground2D:
|
|
|
|
|
var loader = get_ground_loader()
|
|
|
|
|
if loader:
|
|
|
|
|
return loader.ground
|
2025-01-24 14:19:17 +00:00
|
|
|
|
return get_tree().current_scene.get_node_or_null("Ground")
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
2024-12-30 13:19:10 +00:00
|
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
|
func get_camera_marker() -> CameraFocusMarker:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
var ground = get_ground()
|
|
|
|
|
if ground:
|
|
|
|
|
return ground.camera_focus_marker
|
|
|
|
|
return null
|
2024-12-30 13:19:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func get_player() -> MainPlayer:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
var ground = get_ground()
|
|
|
|
|
if ground:
|
|
|
|
|
return ground.player
|
|
|
|
|
return null
|
2024-12-30 13:19:10 +00:00
|
|
|
|
|
2025-01-03 13:29:22 +00:00
|
|
|
|
|
2025-01-31 11:21:41 +00:00
|
|
|
|
func focus_node(node: Node2D, duration := 0.0) -> void:
|
2025-01-21 13:49:37 +00:00
|
|
|
|
var marker = get_camera_marker()
|
|
|
|
|
if marker:
|
2025-01-31 11:21:41 +00:00
|
|
|
|
marker.focus_node(node, duration)
|
2025-01-14 10:20:31 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
|
func focus_player_and_reset_zoom(duration := 1.2) -> void:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
var marker = get_camera_marker()
|
|
|
|
|
if marker:
|
2025-01-24 14:19:17 +00:00
|
|
|
|
# marker.force_offset = Vector2.ZERO
|
2025-01-27 15:13:37 +00:00
|
|
|
|
marker.tween_zoom(1.0, duration)
|
2025-01-31 11:21:41 +00:00
|
|
|
|
# 运镜更平滑一些
|
|
|
|
|
marker.focus_node(get_player(), duration + .3)
|
2025-01-14 10:20:31 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
# action_locked 用于设置界面等强制锁定,action_freezed 用于查看物品等锁定
|
|
|
|
|
# action_locked 优先级高于 action_freezed
|
|
|
|
|
# action_locked 对应 lock 与 unlock 方法
|
|
|
|
|
func lock_player():
|
2025-01-12 06:02:00 +00:00
|
|
|
|
var player = get_player()
|
|
|
|
|
if player:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
player.action_locked = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func unlock_player():
|
|
|
|
|
var player = get_player()
|
|
|
|
|
if player:
|
|
|
|
|
player.action_locked = false
|
|
|
|
|
|
|
|
|
|
|
2025-05-21 20:16:27 +00:00
|
|
|
|
# func is_palyer_operational() -> bool:
|
|
|
|
|
# var player = get_player() as MainPlayer
|
|
|
|
|
# if not player:
|
|
|
|
|
# return true
|
|
|
|
|
# return player.operational
|
|
|
|
|
|
|
|
|
|
# func set_player_operational(val := true):
|
|
|
|
|
# var player = get_player() as MainPlayer
|
|
|
|
|
# if player:
|
|
|
|
|
# player.operational = val
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
# action_freezed 对应 freeze 与 release 方法
|
|
|
|
|
# lock_time: the time to lock the player action. 0 means lock forever, thus the player will be locked until release_player is called.
|
2025-03-12 07:53:12 +00:00
|
|
|
|
func freeze_player(lock_time: float, action := 3, auto_quit := false) -> void:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
var player = get_player()
|
|
|
|
|
if player:
|
|
|
|
|
player.freeze_player(lock_time, action, auto_quit)
|
2025-01-12 06:02:00 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("Player node not found")
|
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func freeze_and_play(lock_time: float, animation := "", auto_quit := false) -> void:
|
2024-12-30 13:19:10 +00:00
|
|
|
|
var player = get_player()
|
|
|
|
|
if player:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
player.freeze_and_play(lock_time, animation, auto_quit)
|
2025-01-08 00:51:09 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("Player node not found")
|
2024-12-27 13:32:12 +00:00
|
|
|
|
|
2025-01-12 06:02:00 +00:00
|
|
|
|
|
2025-01-10 07:43:55 +00:00
|
|
|
|
func release_player():
|
|
|
|
|
var player = get_player()
|
|
|
|
|
if player:
|
|
|
|
|
player.release_player()
|
|
|
|
|
else:
|
|
|
|
|
printerr("Player node not found")
|
2024-12-27 13:32:12 +00:00
|
|
|
|
|
2025-01-12 06:02:00 +00:00
|
|
|
|
|
2025-01-06 08:06:20 +00:00
|
|
|
|
func set_camera_boundary(rect: Rect2) -> void:
|
2025-01-16 12:24:21 +00:00
|
|
|
|
var camera_marker = get_camera_marker()
|
2025-01-06 08:06:20 +00:00
|
|
|
|
camera_marker.limit_left = rect.position.x
|
|
|
|
|
camera_marker.limit_right = rect.position.x + rect.size.x
|
|
|
|
|
camera_marker.limit_top = rect.position.y
|
|
|
|
|
camera_marker.limit_bottom = rect.position.y + rect.size.y
|
2024-12-27 13:32:12 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-06 08:06:20 +00:00
|
|
|
|
func set_player_boundary(rect: Rect2) -> void:
|
2024-12-30 13:19:10 +00:00
|
|
|
|
var player = get_player()
|
2024-12-27 13:32:12 +00:00
|
|
|
|
if player:
|
|
|
|
|
player.player_movement_rect = rect
|
|
|
|
|
else:
|
|
|
|
|
printerr("Player node not found")
|
|
|
|
|
|
2024-12-27 07:56:45 +00:00
|
|
|
|
|
2025-01-21 12:41:24 +00:00
|
|
|
|
var balloon_node
|
|
|
|
|
|
2025-03-12 07:53:12 +00:00
|
|
|
|
|
2025-01-20 13:45:47 +00:00
|
|
|
|
func pop_debug_dialog_info(character: String, content: String):
|
|
|
|
|
if GlobalConfig.DEBUG:
|
2025-01-21 12:41:24 +00:00
|
|
|
|
if not is_instance_valid(balloon_node):
|
|
|
|
|
balloon_node = preload("res://scene/dialog/balloon_debug.tscn").instantiate()
|
2025-01-20 13:45:47 +00:00
|
|
|
|
var title = "title"
|
|
|
|
|
var body = "~ " + title + "\n"
|
|
|
|
|
body += character + ": " + content + "\n"
|
|
|
|
|
body += "=> END"
|
|
|
|
|
var res = DialogueManager.create_resource_from_text(body)
|
2025-01-21 12:41:24 +00:00
|
|
|
|
DialogueManager.show_dialogue_balloon_scene(balloon_node, res, title)
|
2025-01-20 13:45:47 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
#### Prop ####
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func get_prop_hud() -> PropHud:
|
2025-01-21 10:08:16 +00:00
|
|
|
|
return get_node_or_null("/root/Main/UILayer/PropHUD") as PropHud
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
|
|
2025-06-19 06:50:06 +00:00
|
|
|
|
func toggle_hud_display(display_hud: bool):
|
|
|
|
|
var prop_hud = get_prop_hud() as PropHud
|
|
|
|
|
if prop_hud:
|
|
|
|
|
if display_hud:
|
|
|
|
|
prop_hud.display_hud()
|
|
|
|
|
else:
|
|
|
|
|
prop_hud.hide_hud()
|
|
|
|
|
else:
|
|
|
|
|
printerr("toggle_hud_display: PropHud node not found")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func checkout_prop_inventory(inv):
|
|
|
|
|
var prop_hud = get_prop_hud() as PropHud
|
|
|
|
|
if prop_hud:
|
|
|
|
|
prop_hud.checkout_inventory(inv)
|
|
|
|
|
else:
|
|
|
|
|
printerr("checkout_prop_inventory: PropHud node not found")
|
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func get_current_prop(must_selected: bool) -> String:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud and (not must_selected or prop_hud.selected):
|
|
|
|
|
return prop_hud.inventory.current_item_key()
|
|
|
|
|
return ""
|
|
|
|
|
|
2025-06-07 09:04:08 +00:00
|
|
|
|
|
2025-06-18 10:15:49 +00:00
|
|
|
|
func has_prop(prop_key: String) -> bool:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud:
|
|
|
|
|
return prop_hud.inventory.enabled_items.has(prop_key)
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
|
|
|
2025-05-21 20:16:27 +00:00
|
|
|
|
# 静默增加 prop,一般用于提前保存数据,确保数据一致性(防止在 await 时退出等导致丢数据)
|
|
|
|
|
func enable_prop_item_silently(prop_key: String) -> void:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud:
|
2025-05-31 06:45:34 +00:00
|
|
|
|
prop_hud.enable_prop_item(prop_key, false)
|
2025-05-21 20:16:27 +00:00
|
|
|
|
else:
|
2025-06-19 06:50:06 +00:00
|
|
|
|
printerr("enable_prop_item_silently: PropHud node not found")
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
2025-06-07 09:04:08 +00:00
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func enable_prop_item(prop_key: String) -> void:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud:
|
|
|
|
|
prop_hud.enable_prop_item(prop_key)
|
2025-01-30 12:04:02 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("enable_prop_item PropHud node not found")
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
|
|
2025-03-12 07:53:12 +00:00
|
|
|
|
func enable_important_item(prop_key: String) -> void:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud:
|
|
|
|
|
prop_hud.inventory.enable_important_item(prop_key)
|
2025-06-07 09:04:08 +00:00
|
|
|
|
SceneManager.pop_center_notification(tr("ui_important_item_update"))
|
2025-03-12 07:53:12 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("enable_important_item PropHud node not found")
|
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func disable_prop_item(prop_key: String) -> void:
|
|
|
|
|
var prop_hud = get_prop_hud()
|
|
|
|
|
if prop_hud:
|
|
|
|
|
prop_hud.disable_prop_item(prop_key)
|
2025-01-30 12:04:02 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("disable_prop_item PropHud node not found")
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
|
|
2025-06-13 08:03:19 +00:00
|
|
|
|
func pop_os_with_str(translation_key: String, auto_freeze := true, auto_release := true) -> Tween:
|
2025-06-07 09:04:08 +00:00
|
|
|
|
var player = get_player() as MainPlayer
|
2025-01-16 12:24:21 +00:00
|
|
|
|
if player:
|
2025-06-13 08:03:19 +00:00
|
|
|
|
var msg = tr(translation_key).replace("<br>", "\n")
|
|
|
|
|
var lines = await DialogueUtil.generate_lines(msg)
|
|
|
|
|
return player.pop_os(lines, auto_freeze, auto_release)
|
2025-01-16 12:24:21 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("Player node not found")
|
2025-06-13 08:03:19 +00:00
|
|
|
|
return create_tween()
|
2025-06-07 09:04:08 +00:00
|
|
|
|
|
|
|
|
|
|
2024-12-23 01:29:31 +00:00
|
|
|
|
func pop_notification(msg: String, number := 1) -> void:
|
|
|
|
|
var notification_node = get_node_or_null("/root/Main/UILayer/Notification")
|
|
|
|
|
if notification_node:
|
|
|
|
|
notification_node.show_notification(msg, number)
|
2025-01-29 14:05:27 +00:00
|
|
|
|
elif GlobalConfig.DEBUG:
|
|
|
|
|
# debug 模式,新建一个
|
|
|
|
|
var n = _create_debug_notification()
|
|
|
|
|
n.call_deferred("show_notification", msg, number)
|
2024-12-23 01:29:31 +00:00
|
|
|
|
else:
|
2025-01-24 14:19:17 +00:00
|
|
|
|
printerr("pop_notification: Notification node not found")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func pop_center_notification(msg: String) -> void:
|
|
|
|
|
var notification_node = get_node_or_null("/root/Main/UILayer/Notification")
|
|
|
|
|
if notification_node:
|
|
|
|
|
notification_node.show_center_notification(msg)
|
2025-01-29 14:05:27 +00:00
|
|
|
|
elif GlobalConfig.DEBUG:
|
|
|
|
|
# debug 模式,新建一个
|
|
|
|
|
var n = _create_debug_notification()
|
|
|
|
|
n.call_deferred("show_center_notification", msg)
|
2025-01-24 14:19:17 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("pop_center_notification: Notification node not found")
|
2024-12-27 07:56:45 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-29 14:05:27 +00:00
|
|
|
|
func pop_center_texture(texture: Texture2D, duration := 3.5) -> void:
|
|
|
|
|
var notification_node = get_node_or_null("/root/Main/UILayer/Notification")
|
|
|
|
|
if notification_node:
|
|
|
|
|
notification_node.show_center_texture(texture, duration)
|
|
|
|
|
elif GlobalConfig.DEBUG:
|
|
|
|
|
# debug 模式,新建一个
|
|
|
|
|
var n = _create_debug_notification()
|
|
|
|
|
n.call_deferred("show_center_texture", texture)
|
|
|
|
|
else:
|
|
|
|
|
printerr("pop_center_texture: Notification node not found")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# debug 模式,新建一个 notification node
|
|
|
|
|
func _create_debug_notification() -> Notification:
|
|
|
|
|
if not GlobalConfig.DEBUG:
|
|
|
|
|
return null
|
|
|
|
|
var main = get_node_or_null("/root/Main")
|
|
|
|
|
if not main:
|
|
|
|
|
main = Control.new()
|
|
|
|
|
main.set_anchors_preset(Control.PRESET_FULL_RECT)
|
|
|
|
|
main.name = "Main"
|
|
|
|
|
get_tree().root.call_deferred("add_child", main)
|
|
|
|
|
var n = preload("res://scene/notification/notification.tscn").instantiate()
|
|
|
|
|
main.add_child(n)
|
|
|
|
|
return n
|
|
|
|
|
|
|
|
|
|
|
2024-12-27 07:56:45 +00:00
|
|
|
|
func pop_dialog(
|
|
|
|
|
character: String,
|
|
|
|
|
content: String,
|
|
|
|
|
character_color := "orange",
|
|
|
|
|
content_color := "white",
|
|
|
|
|
duration := 2.5
|
|
|
|
|
) -> void:
|
|
|
|
|
var dialog_node = get_node_or_null("/root/Main/UILayer/Dialog")
|
|
|
|
|
if dialog_node:
|
|
|
|
|
dialog_node.append_dialog(character, content, character_color, content_color, duration)
|
|
|
|
|
else:
|
|
|
|
|
printerr("Dialog node not found")
|
|
|
|
|
|
|
|
|
|
|
2025-01-10 07:43:55 +00:00
|
|
|
|
# func pop_note(note: String, note_color := "white", duration := 2.5) -> void:
|
|
|
|
|
# var dialog_node = get_node_or_null("/root/Main/UILayer/Dialog")
|
|
|
|
|
# if dialog_node:
|
|
|
|
|
# dialog_node.append_note(note, note_color, duration)
|
|
|
|
|
# else:
|
|
|
|
|
# printerr("Dialog node not found")
|
2024-12-30 13:19:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func get_inspector() -> PropInspector:
|
|
|
|
|
return get_node_or_null("/root/Main/PropInspector") as PropInspector
|
|
|
|
|
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
2025-06-14 08:46:32 +00:00
|
|
|
|
func checkout_index_page(transition := true):
|
2025-01-16 12:24:21 +00:00
|
|
|
|
ArchiveManager.save_all()
|
2025-06-14 08:46:32 +00:00
|
|
|
|
if transition:
|
|
|
|
|
var ground = get_ground()
|
|
|
|
|
if ground:
|
|
|
|
|
var tween = create_tween()
|
|
|
|
|
tween.tween_property(ground, "modulate:a", 0.0, 1.0)
|
|
|
|
|
tween.tween_callback(_jump_back_to_index_and_quit_main)
|
|
|
|
|
else:
|
|
|
|
|
_jump_back_to_index_and_quit_main()
|
|
|
|
|
else:
|
|
|
|
|
_jump_back_to_index_and_quit_main()
|
|
|
|
|
|
2025-06-18 10:15:49 +00:00
|
|
|
|
|
2025-06-15 09:31:43 +00:00
|
|
|
|
var packed_index_page := preload("res://scene/index_page.tscn")
|
2025-06-14 08:46:32 +00:00
|
|
|
|
|
2025-06-18 10:15:49 +00:00
|
|
|
|
|
2025-06-14 08:46:32 +00:00
|
|
|
|
func _jump_back_to_index_and_quit_main():
|
2025-06-15 09:31:43 +00:00
|
|
|
|
# 技术问题:DialogueManager 中 do SceneManager.checkout_index_page()时,checkout scene 原本 /root/Main 节点未被删除
|
|
|
|
|
# * 原本除 standalone 的节点外,只有 /root/Main (current_scene)
|
|
|
|
|
# * checkout 后,/root 下同时存在 Index 页面节点与 Main 节点
|
|
|
|
|
# * 导致 Camera 仍旧在 Main 下,仍旧可以切换道具,但是玩家不能移动(玩家 Input 失效)
|
|
|
|
|
# * 手动 queue_free 原 Main 节点可行
|
|
|
|
|
# * 阅读 SceneTree 的 cpp 源码,change_scene_to_packed 看似无异常
|
|
|
|
|
# 问题出现在 Ground 中 get_node("/root").add_child(main)
|
|
|
|
|
# 需要再指定 current_scene: get_tree().current_scene = main
|
|
|
|
|
get_tree().change_scene_to_packed(packed_index_page)
|
2025-06-15 05:11:41 +00:00
|
|
|
|
# var main = get_node_or_null("/root/Main")
|
|
|
|
|
# if main:
|
|
|
|
|
# main.queue_free()
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-21 12:41:24 +00:00
|
|
|
|
var prop_bag = preload("res://scene/prop/prop_bag.tscn")
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-21 12:41:24 +00:00
|
|
|
|
func show_bag():
|
2025-03-12 07:53:12 +00:00
|
|
|
|
get_node("/root/Main").add_child(prop_bag.instantiate())
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func quit_game():
|
|
|
|
|
ArchiveManager.save_all()
|
|
|
|
|
get_tree().quit()
|