diff --git a/README.md b/README.md index 0acac436..19296df8 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,24 @@ func _parse_node(ground_node, node:Node, existing_vars:Dictionary, code_lines:Pa ## 线索笔记说明 +1. Aseprite 中编辑 slice 区域,配置区域名: c02_slices.ase +2. aseprite_slice_to_atlas.tscn 自动生成切图 +3. 在 ux_note.tscn 中使用切图 +4. 多语言本地化使用 c02_slices.ase 的不同图层导出,如 c02_slices.png 与 c02_slices_en.png + + +## Event 系统说明 + +1. 事件阶段管理:event_stage.dialogue +2. 事件绑定:EventBinder + - 通过事件阶段,控制父节点的显示/启用状态 + - 订阅父节点交互 signal ,更新事件阶段 +3. 复杂事件集合:Event2D + - 自动生成并绑定脚本,用脚本更灵活地控制子节点状态 + - 配合 ProAnimatedSprite 节点,可在编辑器直接预览小动画 +4. memo 备忘系统: + - 自动读取 event_stage.dialogue 的信息,写入到 EventBinder/Event2D 的 memo 中 + - EventBinder/Event2D 的阶段 Checkbox 的 tooltip 提示文本可以看到序号所对应的阶段名 ## 存档结构 @@ -164,3 +182,4 @@ current_scene 是通过 GroundLoader 加载的,在 ground loader 加载 ground - 转场 process 机制优化:暂停 & AnimationPlayer 保持运行 - EventManager 控制事件,使用 Event2D 控制绑定关系 - Vibe Control 控制氛围情绪音乐 + diff --git a/addons/dialogue_manager/dialogue_manager.gd b/addons/dialogue_manager/dialogue_manager.gd index 3857f319..e43f2807 100644 --- a/addons/dialogue_manager/dialogue_manager.gd +++ b/addons/dialogue_manager/dialogue_manager.gd @@ -1,3 +1,4 @@ +@tool extends Node const DialogueResource = preload("./dialogue_resource.gd") diff --git a/addons/dialogue_manager/dialogue_resource.gd b/addons/dialogue_manager/dialogue_resource.gd index 904b9a95..27e0d93c 100644 --- a/addons/dialogue_manager/dialogue_resource.gd +++ b/addons/dialogue_manager/dialogue_resource.gd @@ -30,7 +30,7 @@ const DialogueLine = preload("./dialogue_line.gd") ## be a title string or a stringified line number). Runs any mutations along the way and then returns ## the first dialogue line encountered. func get_next_dialogue_line(title: String = "", extra_game_states: Array = [], mutation_behaviour: DMConstants.MutationBehaviour = DMConstants.MutationBehaviour.Wait) -> DialogueLine: - return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) + return await DialogueManager.get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) ## Get the list of any titles found in the file. diff --git a/addons/property-inspector/event_2d/checked.png b/addons/property-inspector/event_2d/checked.png new file mode 100755 index 00000000..40d6f527 Binary files /dev/null and b/addons/property-inspector/event_2d/checked.png differ diff --git a/addons/property-inspector/event_2d/checked.png.import b/addons/property-inspector/event_2d/checked.png.import new file mode 100644 index 00000000..58ef029b --- /dev/null +++ b/addons/property-inspector/event_2d/checked.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dhan4svvxtqwd" +path="res://.godot/imported/checked.png-cb94f802c96994b2840cade9448d51ae.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/property-inspector/event_2d/checked.png" +dest_files=["res://.godot/imported/checked.png-cb94f802c96994b2840cade9448d51ae.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/property-inspector/event_2d/radio_checked.png.import b/addons/property-inspector/event_2d/radio_checked.png.import new file mode 100644 index 00000000..62184eff --- /dev/null +++ b/addons/property-inspector/event_2d/radio_checked.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://rq4dsxooay2" +path="res://.godot/imported/radio_checked.png-e28720cbc9fafadcb0954b33d0f47b82.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/property-inspector/event_2d/radio_checked.png" +dest_files=["res://.godot/imported/radio_checked.png-e28720cbc9fafadcb0954b33d0f47b82.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/property-inspector/event_2d/stages_editor.gd b/addons/property-inspector/event_2d/stages_editor.gd new file mode 100644 index 00000000..815ebb01 --- /dev/null +++ b/addons/property-inspector/event_2d/stages_editor.gd @@ -0,0 +1,85 @@ +extends EditorProperty + +var h_box: HBoxContainer = HBoxContainer.new() +var stage_nodes := [] + +var updating = false +var property_name: String + + +func _init(p_name) -> void: + property_name = p_name + add_child(h_box) + + +func _get_property() -> Array[Dictionary]: + return get_edited_object()[property_name] + + +func _update_property() -> void: + # Clear the control. + for s in stage_nodes: + s.queue_free() + stage_nodes.clear() + _reload_stages() + + +var box_checked_texture = preload("res://addons/property-inspector/event_2d/checked.png") +var box_unchecked_texture = preload("res://addons/property-inspector/event_2d/unchecked.png") + + +func _make_unique_and_sort(arr: Array[int]) -> void: + var unique_arr: Array[int] = [] + for element in arr: + if not element in unique_arr: + unique_arr.append(element) + unique_arr.sort() + arr.assign(unique_arr) + + +func _reload_stages(): + var obj = get_edited_object() + if obj == null: + printerr("obj is null") + return + var stages = obj[property_name] as Array[int] + var event_name + if property_name == "pre_event_stages": + event_name = obj["pre_event_name"] + elif property_name == "event_stages": + event_name = obj["event_name"] + elif property_name == "updater_stages": + event_name = obj["updater_event"] + var stages_name: PackedStringArray = await EventManager.get_event_stage_map_array(event_name) + # print("stages:", stages) + h_box.add_theme_constant_override("separation", 1) + for i in 7: + # make the text inside the box + var container := AspectRatioContainer.new() + container.set_anchors_preset(PRESET_FULL_RECT) + var box: CheckBox = CheckBox.new() as CheckBox + box.button_pressed = i in stages + box.toggled.connect(_on_toggle_checkbox.bind(i)) + box.add_theme_icon_override("checked", box_checked_texture) + box.add_theme_icon_override("unchecked", box_unchecked_texture) + container.add_child(box) + var label := Label.new() + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + container.add_child(label) + label.text = str(i) + h_box.add_child(container) + stage_nodes.append(container) + if stages_name.size() > i: + box.tooltip_text = stages_name[i] + + +func _on_toggle_checkbox(on: bool, id: int): + # 防止 read-only 所以 duplicate + var arr = get_edited_object()[property_name].duplicate() + if on: + arr.append(id) + else: + arr.erase(id) + _make_unique_and_sort(arr) + emit_changed(property_name, arr) + get_edited_object()._auto_memo() diff --git a/addons/property-inspector/event_2d/stages_editor.gd.uid b/addons/property-inspector/event_2d/stages_editor.gd.uid new file mode 100644 index 00000000..022389a9 --- /dev/null +++ b/addons/property-inspector/event_2d/stages_editor.gd.uid @@ -0,0 +1 @@ +uid://bjsrudsa3cpyx diff --git a/addons/property-inspector/event_2d/unchecked.png b/addons/property-inspector/event_2d/unchecked.png new file mode 100755 index 00000000..03ddbece Binary files /dev/null and b/addons/property-inspector/event_2d/unchecked.png differ diff --git a/addons/property-inspector/event_2d/unchecked.png.import b/addons/property-inspector/event_2d/unchecked.png.import new file mode 100644 index 00000000..bde11920 --- /dev/null +++ b/addons/property-inspector/event_2d/unchecked.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c8un06r0tg2ur" +path="res://.godot/imported/unchecked.png-ec639bca865e24a176cd170b2f702f9a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/property-inspector/event_2d/unchecked.png" +dest_files=["res://.godot/imported/unchecked.png-ec639bca865e24a176cd170b2f702f9a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/property-inspector/inspector.gd b/addons/property-inspector/inspector.gd index 2bb38db0..723c5b60 100644 --- a/addons/property-inspector/inspector.gd +++ b/addons/property-inspector/inspector.gd @@ -2,10 +2,11 @@ extends EditorInspectorPlugin var move_editor = preload("pro_animation_sprite2d/pro_animation_move_editor.gd") var action_editor = preload("pro_animation_sprite2d/pro_animation_action_editor.gd") +var stages_editor = preload("event_2d/stages_editor.gd") func _can_handle(object): - return object is ProAnimatedSprite2D + return object is ProAnimatedSprite2D or object is Event2D or object is EventBinder func _parse_property(object, type, name, hint_type, hint_string, usage_flags, wide): @@ -17,5 +18,7 @@ func _parse_property(object, type, name, hint_type, hint_string, usage_flags, wi elif name == "action_configs": add_property_editor(name, action_editor.new()) return true - else: - return false + elif name == "pre_event_stages" or name == "event_stages" or name == "updater_stages": + add_property_editor(name, stages_editor.new(name)) + return true + return false diff --git a/asset/dialogue/event_stage.dialogue b/asset/dialogue/event_stage.dialogue index c46c9c34..6029fe21 100644 --- a/asset/dialogue/event_stage.dialogue +++ b/asset/dialogue/event_stage.dialogue @@ -1,19 +1,23 @@ -~ EventStage -# 0demo 1release -release_stage - -# 0:关闭 1:打开 2:放入小蝉人偶 3:全部放置正确_可摇手柄 4:已播放完成 -c02_musicbox_stage -# 1:已交互疯子 2:小鞋已掉落 -c02_madman_interacted_stage -# 0:默认 1:寻找弹珠_老虎钳可以换弹珠 2:给出弹珠 3:游戏结束_小猫纸片 4:游戏结束_小猫离开 -c02_ball_game_stage - -# c03 第二章 -# 0未开始 1邀请 2完成 -c03_invite_xchan_supper - +~ EventStage_c00 +release_stage: 0:demo 1:release => END -~ ArchiveStage +~ EventStage_c02 +c02_musicbox_stage: 0:初始化_关闭 1:打开 2:放入小蝉人偶 3:全部放置正确_可摇手柄 4:已播放完成 +c02_madman_interacted_stage: 0:初始化 1:已交互疯子 2:小鞋已掉落 +c02_ball_game_stage: 0:初始化 1:寻找弹珠_老虎钳可以换弹珠 2:给出弹珠 3:游戏结束_小猫纸片 4:游戏结束_小猫离开 +=> END + +~ EventStage_c03 +c03_s01_meat_put: 0:初始化 1:已放肉 +c03_invite_xchan_supper: 0:初始化 1:已偷听_需邀请 2:已完成邀请 +=> END + +~ EventStage_c04 +=> END + +~ EventStage_c05 +=> END + +~ EventStage_c06 => END \ No newline at end of file diff --git a/manager/event_manager/event2d.gd b/manager/event_manager/event2d.gd index 7b849e0f..848b0596 100644 --- a/manager/event_manager/event2d.gd +++ b/manager/event_manager/event2d.gd @@ -45,6 +45,7 @@ func _ready() -> void: # if event_name != &"": # name = "Event_" + event_name if Engine.is_editor_hint(): + _auto_memo() return if event_name != "": stage = EventManager.get_stage(event_name) @@ -150,17 +151,20 @@ func _copy_getter(): func _auto_memo() -> void: var memo_str := "" + # if EventManager if pre_event_name != &"" and pre_event_mode != "none": memo_str += "当前置事件[" memo_str += pre_event_name memo_str += "=" if pre_event_mode == "show" else "!=" - memo_str += "|".join(pre_event_stages) + "]" + var stages = await EventManager.map_event_stages(pre_event_name, pre_event_stages) + memo_str += "|".join(stages) + "]" if event_name != &"" and event_mode != "none": memo_str += "" if memo_str.is_empty() else "\n并且" memo_str += "当事件[" memo_str += event_name memo_str += "=" if event_mode == "show" else "!=" - memo_str += "|".join(event_stages) + "]时" + var stages = await EventManager.map_event_stages(event_name, event_stages) + memo_str += "|".join(stages) + "]时" memo_str += "" if memo_str.is_empty() else "显示该节点" var existing_lines = event_memo.split("\n") # 保留 # 开头的 line diff --git a/manager/event_manager/event_binder.gd b/manager/event_manager/event_binder.gd index 899a1147..8b155ec3 100644 --- a/manager/event_manager/event_binder.gd +++ b/manager/event_manager/event_binder.gd @@ -169,12 +169,14 @@ func _auto_memo() -> void: if updater_event != "": memo_str = updater_event memo_str += "=" if updater_stage_mode == "include" else "!=" - memo_str += "|".join(updater_stages) + " 时," + var stages = await EventManager.map_event_stages(updater_event, updater_stages) + memo_str += "[" + "|".join(stages) + "] 时," memo_str += "显示" if updater_mode == "shower" else "启用" memo_str += ": [" + parent_name + "]\n" if trigger_event != "" and trigger_mode != "none": memo_str += "[" + parent_name + "] " + trigger_mode + " 时: " - memo_str += trigger_event + "=" + str(trigger_stage) + var stages = await EventManager.map_event_stages(trigger_event, [trigger_stage]) + memo_str += trigger_event + "=" + str(stages[0]) memo_str += "(greater)" if trigger_set_stage_if_greater else "(any)" var existing_lines = memo.split("\n") # 保留 # 开头的 line diff --git a/manager/event_manager/event_manager.gd b/manager/event_manager/event_manager.gd index 6fc1bf6d..77a94c47 100644 --- a/manager/event_manager/event_manager.gd +++ b/manager/event_manager/event_manager.gd @@ -1,9 +1,12 @@ +@tool extends Node signal stage_updated(event_name: StringName, stage: int) func _ready() -> void: + if Engine.is_editor_hint(): + return # 0demo 1release set_stage("release_stage", GlobalConfig.RELEASE_STAGE) @@ -67,3 +70,67 @@ func next_staged(event_name: StringName, stage_max := 99999) -> void: func prop_interacted(e_name, prop_key, interacted_times) -> void: print("Event: %s interacted with %s. total times: %s" % [e_name, prop_key, interacted_times]) + + +##### TOOL 方法 + +# event_name -> {stages:PackedStringArray, update_time:int} +var _debug_event_stage_dict := {} + + +# return: stages +func get_event_stage_map_array(event_name: StringName) -> PackedStringArray: + if not Engine.is_editor_hint(): + return PackedStringArray() + var current_dict = _debug_event_stage_dict.get(event_name) + var time_msec = Time.get_ticks_msec() + # 3秒更新 + if current_dict and time_msec - current_dict["update_time"] < 3000: + return current_dict["stages"] + # 文件: res://asset/dialogue/event_stage.dialogue + var event_stage_resource = load("uid://dohpsb4jttuv1") as DialogueResource + for title in event_stage_resource.get_titles(): + var lines = await Util.get_lines(event_stage_resource, title) + for line in lines: + var line_text = line.text.strip_edges() + var e_name = line.character + if line_text.begins_with("#"): + continue + #c03_invite_xchan_supper: 0:未开始 1:已偷听,需邀请 2:已完成邀请 + var parts = line_text.split(" ") + var stages = PackedStringArray() + for id in range(0, len(parts)): + var tuple = parts[id].split(":") + if len(tuple) == 2: + var event_stage = int(tuple[0]) + if stages.size() < event_stage + 1: + stages.resize(event_stage + 1) + stages[event_stage] = tuple[1] + for id in len(stages): + if stages[id] == "": + stages[id] = str(id) + _debug_event_stage_dict[e_name] = { + "stages": stages, + "update_time": time_msec, + } + if _debug_event_stage_dict.has(event_name): + prints("reload", event_name, "stages:", _debug_event_stage_dict[event_name]["stages"]) + return _debug_event_stage_dict[event_name]["stages"] + return PackedStringArray() + + +# map stage_id->name, 必定保持相同长度的数组 +func map_event_stages( + event_name: StringName, stages: Array, including_id := true +) -> PackedStringArray: + var result = PackedStringArray() + result.resize(stages.size()) + var dict = await get_event_stage_map_array(event_name) + for id in range(stages.size()): + var stage = stages[id] + if dict.size() > stage: + if including_id: + result[id] = str(stage) + ":" + dict[stage] + else: + result[id] = str(stage) + return result diff --git a/manager/scene/scene_manager.gd b/manager/scene/scene_manager.gd index 1145651d..20b5e3f1 100644 --- a/manager/scene/scene_manager.gd +++ b/manager/scene/scene_manager.gd @@ -206,9 +206,7 @@ func enable_prop_item(prop_key: String) -> void: func enable_important_item(prop_key: String, display_inspector = true) -> void: var prop_hud = get_prop_hud() if prop_hud: - prop_hud.inventory.enable_important_item(prop_key) - # if display_inspector: - # prop_hud.display_inspector(prop_key) + prop_hud.enable_important_item(prop_key, display_inspector) else: printerr("enable_important_item PropHud node not found") diff --git a/scene/ground/scene/c02/s06_二楼.tscn b/scene/ground/scene/c02/s06_二楼.tscn index a201807c..ec697215 100644 --- a/scene/ground/scene/c02/s06_二楼.tscn +++ b/scene/ground/scene/c02/s06_二楼.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=66 format=3 uid="uid://cootarwb44vvh"] +[gd_scene load_steps=67 format=3 uid="uid://cootarwb44vvh"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_qkymk"] [ext_resource type="Script" uid="uid://cbt0ubygchxvv" path="res://scene/ground/scene/c02/s06_二楼.gd" id="2_4dg6u"] @@ -46,6 +46,7 @@ [ext_resource type="Texture2D" uid="uid://b5kolhax7pf4u" path="res://asset/art/scene/c02/s06_二楼楼道/小猫纸条.png" id="37_rjlld"] [ext_resource type="Script" uid="uid://bnm8wuspfx303" path="res://scene/ground/script/c02/event_2d_xchan_run_away.gd" id="39_t5e0j"] [ext_resource type="SpriteFrames" uid="uid://di43shn22n5ph" path="res://asset/art/gif/c00_通用动作/c00_通用动作_frames.tres" id="40_7i4w0"] +[ext_resource type="Script" uid="uid://n56a07gyjq1u" path="res://scene/ground/script/c03/s02_event_2d偷听陆仁小蝶对话后.gd" id="46_sqio2"] [sub_resource type="Animation" id="Animation_k01ve"] length = 0.001 @@ -971,6 +972,8 @@ prop_key = "prop_不存在的钥匙" [node name="EventBinder开门" type="Node" parent="Ground/DeployLayer/portal_5"] script = ExtResource("10_0k27j") +memo = "current_chapter_stage!=1|2 时,启用: [_5] +" updater_event = &"current_chapter_stage" updater_stage_mode = "exclude" updater_stages = Array[int]([1, 2]) @@ -1307,6 +1310,7 @@ position = Vector2(164, 42) script = ExtResource("35_h3h1a") pre_event_name = &"c02_ball_game_stage" pre_event_stages = Array[int]([3]) +event_memo = "当前置事件[c02_ball_game_stage=0]显示该节点" metadata/_custom_type_script = "uid://bkkiyk5jkdw4d" [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="Ground/DeployLayer/Event_小猫纸条"] @@ -1331,6 +1335,7 @@ position = Vector2(9, -4) script = ExtResource("39_t5e0j") event_name = &"c02_2f_xchan_run_away" event_stages = Array[int]([1]) +event_memo = "当事件[c02_2f_xchan_run_away=0]时显示该节点" metadata/_custom_type_script = "uid://bkkiyk5jkdw4d" [node name="Ambush走到尽头后小蝉跑" parent="Ground/DeployLayer/Event2D_xchan_run_away" instance=ExtResource("14_k01ve")] @@ -1352,6 +1357,13 @@ move_configs = Array[Dictionary]([{ }]) debug_mov_animation = "c00_头套小婵_run" +[node name="Event2D偷听陆仁对话后" type="Node2D" parent="Ground/DeployLayer" index="24"] +script = ExtResource("46_sqio2") +event_name = &"c03_invite_xchan_supper" +event_stages = Array[int]([2]) +event_memo = "当事件[c03_invite_xchan_supper=2:已完成邀请]时显示该节点" +metadata/_custom_type_script = "uid://bkkiyk5jkdw4d" + [node name="MainPlayer" parent="Ground" index="5"] position = Vector2(63, 95) catty_light_energy = 0.5 diff --git a/scene/ground/scene/c03/s01_三楼.tscn b/scene/ground/scene/c03/s01_三楼.tscn index 83d312ca..0e36955a 100644 --- a/scene/ground/scene/c03/s01_三楼.tscn +++ b/scene/ground/scene/c03/s01_三楼.tscn @@ -216,7 +216,7 @@ prop_key = "prop_奇怪的肉" [node name="EventBinder" type="Node" parent="Ground/DeployLayer/Interactable放肉处"] script = ExtResource("6_yaa68") -memo = "[放肉处] interacted时c03_s01_meat_put=1(greater)" +memo = "[放肉处] interacted 时: c03_s01_meat_put=1:已放肉(greater)" trigger_event = &"c03_s01_meat_put" trigger_mode = "interacted" metadata/_custom_type_script = "uid://0wjaho6qkg6s" @@ -225,7 +225,7 @@ metadata/_custom_type_script = "uid://0wjaho6qkg6s" script = ExtResource("7_obrgj") event_name = &"c03_s01_meat_put" event_stages = Array[int]([1]) -event_memo = "c03_s01_meat_put=0|2" +event_memo = "当事件[c03_s01_meat_put=1:已放肉]时显示该节点" metadata/_custom_type_script = "uid://bkkiyk5jkdw4d" [node name="窗口闪动" type="AnimatedSprite2D" parent="Ground/DeployLayer/Event2D放肉后"] @@ -247,7 +247,7 @@ packed_scene = ExtResource("7_d27sg") [node name="EventBinder" type="Node" parent="Ground/DeployLayer/Event2D放肉后/CloseupDemo公告"] script = ExtResource("6_yaa68") -memo = "release_stage=0 时,显示: [公告] +memo = "release_stage=[0:demo] 时,显示: [公告] " updater_event = &"release_stage" updater_mode = "shower" @@ -358,10 +358,10 @@ hook_method = "eavesdrop_luren" [node name="EventBinder" type="Node" parent="Ground/DeployLayer/Ambush偷听陆仁"] script = ExtResource("6_yaa68") -memo = "c03_s01_meat_put=1 时,启用: [偷听陆仁] -[偷听陆仁] triggered 时: c03_偷听并邀请小蝶=1(greater)" +memo = "c03_s01_meat_put=[1:已放肉] 时,启用: [偷听陆仁] +[偷听陆仁] triggered 时: c03_invite_xchan_supper=1:已偷听_需邀请(greater)" updater_event = &"c03_s01_meat_put" -trigger_event = &"c03_偷听并邀请小蝶" +trigger_event = &"c03_invite_xchan_supper" trigger_mode = "triggered" metadata/_custom_type_script = "uid://0wjaho6qkg6s" diff --git a/scene/ground/scene/c03/s02_瞎子新卧室.tscn b/scene/ground/scene/c03/s02_瞎子新卧室.tscn index 74bec00d..3607c422 100644 --- a/scene/ground/scene/c03/s02_瞎子新卧室.tscn +++ b/scene/ground/scene/c03/s02_瞎子新卧室.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=17 format=3 uid="uid://ctwy1ubhm68la"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_jad6f"] -[ext_resource type="Script" path="res://scene/ground/scene/c03/s02_瞎子新卧室.gd" id="2_y504i"] +[ext_resource type="Script" uid="uid://tk4wg0i4payx" path="res://scene/ground/scene/c03/s02_瞎子新卧室.gd" id="2_y504i"] [ext_resource type="Script" uid="uid://cpejxlfni6n52" path="res://manager/audio_manager/vibe_sfx.gd" id="3_kchgf"] [ext_resource type="Texture2D" uid="uid://vc2hn6t5bedg" path="res://asset/art/scene/c03/s02_瞎子新卧室/bg_瞎子新卧室.png" id="4_hehhg"] [ext_resource type="Texture2D" uid="uid://7ay1ttob8qwm" path="res://asset/art/scene/c02/s08_瞎子卧室/e_床板.png" id="5_xifhb"] @@ -179,19 +179,25 @@ texture = ExtResource("7_u55tr") [node name="Event2D偷听陆仁对话后" type="Node2D" parent="Ground/DeployLayer" index="4"] script = ExtResource("8_pixqd") -event_name = &"c03_偷听并邀请小蝶" +event_name = &"c03_invite_xchan_supper" event_stages = Array[int]([1]) -event_memo = "当事件[c03_偷听并邀请小蝶=1]时显示该节点" +event_memo = "当事件[c03_invite_xchan_supper=1:已偷听_需邀请]时显示该节点" metadata/_custom_type_script = "uid://bkkiyk5jkdw4d" [node name="瞎子抽烟" parent="Ground/DeployLayer/Event2D偷听陆仁对话后" instance=ExtResource("10_jad6f")] position = Vector2(229, 39) sprite_frames = ExtResource("10_2hv3f") animation = &"瞎子_咳嗽吐血" -frame = 28 action_configs = Array[Dictionary]([{ &"animation_intro": "瞎子_抽烟", -&"animation_next": "瞎子_坐拿烟_左呼吸" +&"animation_next": "瞎子_坐拿烟_左呼吸", +"animation_wait_time": 0.0, +"intro_loop": 1 +}, { +"animation_intro": "瞎子_咳嗽吐血", +&"animation_next": "瞎子_坐拿烟_左呼吸", +"animation_wait_time": 0.0, +"intro_loop": 1 }]) [node name="MainPlayer" parent="Ground" index="5"] diff --git a/scene/ground/script/c03/s02_event_2d偷听陆仁小蝶对话后.gd b/scene/ground/script/c03/s02_event_2d偷听陆仁小蝶对话后.gd index 700bc273..42ddf236 100644 --- a/scene/ground/script/c03/s02_event_2d偷听陆仁小蝶对话后.gd +++ b/scene/ground/script/c03/s02_event_2d偷听陆仁小蝶对话后.gd @@ -16,9 +16,15 @@ func _on_global_stage_updated(e: StringName, s: int): func _on_ground_ready(ground: Ground2D): - if stage == 0: - # 邀请小蝉晚饭 - EventManager.set_stage(event_name, 1) + # 邀请小蝉晚饭 + if stage == 1: + var the_blind = $"瞎子抽烟" as AnimatedSprite2D + the_blind.play("瞎子_抽烟") + await the_blind.animation_finished + the_blind.play("瞎子_咳嗽吐血") + await the_blind.animation_finished + # 邀请成功 + EventManager.set_stage(event_name, 2) func _on_pre_stage_updated(): diff --git a/scene/ux/prop_hud.gd b/scene/ux/prop_hud.gd index 26eb6bbd..e6ffb248 100644 --- a/scene/ux/prop_hud.gd +++ b/scene/ux/prop_hud.gd @@ -460,6 +460,18 @@ func _toggle_btn_ability(v: bool) -> void: right_btn.disabled = !v +func enable_important_item(prop_key: String, display_inspector: bool) -> void: + if not inventory or not prop_key: + return + if not items_dict.has(prop_key): + push_error("ImportantPropItem not found! key=" + prop_key) + return + inventory.enable_important_item(prop_key) + SceneManager.pop_notification("ui_notify_important_item_update") + if display_inspector: + inspect_item(prop_key) + + func enable_prop_item(prop_key: String, inspect := true) -> void: if not inventory or not prop_key: return @@ -480,13 +492,17 @@ func enable_prop_item(prop_key: String, inspect := true) -> void: func inspect_item(prop_key: String, display_words_only := false): var inspector = SceneManager.get_inspector() if inspector: + var texture_path = items_dict[prop_key].texture_path var inspect_path = items_dict[prop_key].inspect_path # 是否有独立的 inspect 图片 if inspect_path: var texture = load(inspect_path) as Texture2D inspector.pop_prop_inspection(prop_key, texture, false, display_words_only) else: - var texture = cached_inventory_textures[prop_key] + var texture = cached_inventory_textures.get(prop_key) + if not texture: + texture = load(texture_path) as Texture2D + cached_inventory_textures[prop_key] = texture inspector.pop_prop_inspection(prop_key, texture, true, display_words_only) diff --git a/scene/ux/prop_inspector.gd b/scene/ux/prop_inspector.gd index 865ce7de..61caf405 100644 --- a/scene/ux/prop_inspector.gd +++ b/scene/ux/prop_inspector.gd @@ -20,7 +20,6 @@ signal quit_and_hidden @onready var content_label = %ContentLabel as Label @onready var tip_label = %TipLabel as Label - var tip_cover = "Q: " + tr("ui_退出") + " " + "E: " + tr("ui_阅读") var tip_notes = "Q: " + tr("ui_退出") + " " + "E: " + tr("ui_收起") var texture_cover: Texture2D @@ -162,8 +161,10 @@ func pop_prop_inspection( if not display_words_only: text += obtain_str + ": " + prop_title + "[#item]\n" # 道具的一句话说明 - text += tr(prop_key + "_说明").replace("{br}", "\n").strip_edges() + "\n" - text += "=> END" + var original_word_lines = tr(prop_key + "_说明").replace("{br}", "\n").split("\n") + # 缩略只要第一行 + text += original_word_lines[0] + ("..." if len(original_word_lines) > 1 else "") + text += "\n=> END" var current_prop_res = DialogueManager.create_resource_from_text(text) # 手动跳过的同时显示下一句 if is_instance_valid(balloon): diff --git a/scene/ux/prop_inventory_resource.gd b/scene/ux/prop_inventory_resource.gd index e2c77f32..c663e6cc 100644 --- a/scene/ux/prop_inventory_resource.gd +++ b/scene/ux/prop_inventory_resource.gd @@ -41,7 +41,6 @@ func enable_important_item(prop_key: String) -> void: if not important_items.has(prop_key): important_items.append(prop_key) unviewed_important_items.append(prop_key) - SceneManager.pop_notification("ui_notify_important_item_update") func has_prop(prop_key: String) -> bool: diff --git a/util/util.gd b/util/util.gd index 9616dcff..bdd7b445 100644 --- a/util/util.gd +++ b/util/util.gd @@ -1,6 +1,6 @@ +@tool extends Node - #### Timer func wait(duration: float) -> void: if duration <= 0: