00_Main.gd
· 5.2 KiB · GDScript3
原始檔案
Playground
# warning-ignore-all:return_value_discarded
extends HBoxContainer
class_name ChitinousCanrival
const event_player_scene = preload("res://scenes/ui/EventPlayer.tscn")
@onready var MinigameHandler := %MinigameHandler as MinigameHandler
@onready var TravelButtons := %TravelButtons as TravelButtons
@onready var EventPlayerContainer := %EventPlayerContainer as EventPlayerContainer
@onready var InventoryMenu := %InventoryMenu as InventoryMenu
@onready var SettingsMenu := %SettingsMenu as SettingsMenu
@onready var SaveMenu := %SaveMenu as SaveMenu
@onready var ChoicePanel := %ChoicePanel as Choice
@onready var StatusPanel := %StatusPanel as StatusPanel
@onready var Blackout := %BlackoutPanel as BlackoutPanel
var _current_sequence: String = ""
func _ready() -> void:
randomize()
MusicState.change_bg(MusicState.BACKGROUND_THEME)
ExploreState.set_start_time()
ExploreState._set_location(SimpleState.state.explore.location)
TravelButtons.set_button_disabled(SimpleState.state.explore.location)
SaveState.save_loaded.connect(_on_save_loaded)
EventPlayerContainer.minigame_started.connect(_on_minigame_started)
MinigameHandler.minigame_finished.connect(_on_minigame_finished)
StatusPanel.inventory_button_toggled.connect(_on_inventory_button_toggled)
StatusPanel.settings_button_toggled.connect(_on_settings_button_toggled)
StatusPanel.save_button_toggled.connect(_on_save_button_toggled)
InventoryMenu.visibility_changed.connect(_on_menu_visibility_changed)
SaveMenu.visibility_changed.connect(_on_menu_visibility_changed)
SaveMenu.closed.connect(StatusPanel.saving_closed)
SettingsMenu.visibility_changed.connect(_on_menu_visibility_changed)
SettingsMenu.closed.connect(StatusPanel.settings_closed)
TravelButtons.waited.connect(_on_wait_button_pressed)
ChoicePanel.options_shown.connect(_on_options_shown)
ChoicePanel.options_cleared.connect(_on_options_cleared)
ExploreState.trap_triggered.connect(_on_trap_triggered)
ExploreState.event_triggered.connect(_on_event_triggered)
ExploreState.event_trigger_forced.connect(_on_event_trigger_forced)
ExploreState.revisited.connect(_on_revisited)
ExploreState.wandered.connect(_on_wandered)
ExploreState.item_selected.connect(_on_item_selected)
ExploreState.masturbated.connect(_on_masturbated)
if not MemoryState.has_seen("00-intro/00-premise"):
InventoryState.add_trap("intro")
EventPlayerContainer.run("00-intro/00-premise")
if not SimpleState.state.sequence.current_sequence != "None":
EventPlayerContainer.restore_from_state()
await Blackout.fade_in()
func _on_revisited(event: String) -> void:
EventPlayerContainer.run(event)
func _on_wandered(where: String) -> void:
EventPlayerContainer.run("01-location/%s/wander" % where)
func _on_item_selected(what: String) -> void:
StatusPanel.inventory_closed()
EventPlayerContainer.run("items/%s" % what)
func _on_save_loaded(title) -> void:
if not title:
await Blackout.fade_out()
EventPlayerContainer.hard_stop()
ChoicePanel.clear_options()
if SimpleState.state.sequence.current_sequence != "NONE":
EventPlayerContainer.restore_from_state()
else:
EventPlayerContainer.hide()
await Blackout.fade_in()
func _on_minigame_started(minigame: String, initial_state: Dictionary) -> void:
MinigameHandler.play_minigame(minigame, initial_state)
func _on_minigame_finished(result) -> void:
EventPlayerContainer.minigame_finished(result)
func _on_inventory_button_toggled(pressed: bool) -> void:
InventoryMenu.visible = pressed
if pressed:
SettingsMenu.visible = false
StatusPanel.settings_closed()
SaveMenu.visible = false
StatusPanel.saving_closed()
func _on_settings_button_toggled(pressed: bool) -> void:
SettingsMenu.visible = pressed
if pressed:
InventoryMenu.visible = false
StatusPanel.inventory_closed()
SaveMenu.visible = false
StatusPanel.saving_closed()
func _on_save_button_toggled(pressed: bool) -> void:
SaveMenu.visible = pressed
if pressed:
InventoryMenu.visible = false
StatusPanel.inventory_closed()
SettingsMenu.visible = false
StatusPanel.settings_closed()
func _on_menu_visibility_changed() -> void:
EventPlayerContainer.set_input_disabled(any_menu_open())
ChoicePanel.visible = !any_menu_open() and ChoicePanel.active
func _on_wait_button_pressed() -> void:
await Blackout.fade_out()
ExploreState.wait()
await Blackout.fade_in()
func _on_options_shown() -> void:
ChoicePanel.visible = !any_menu_open() and ChoicePanel.active
func _on_options_cleared() -> void:
ChoicePanel.hide()
await get_tree().process_frame
func _on_trap_triggered(_trap_name: String, event: String) -> void:
EventPlayerContainer.run(event)
func _on_event_triggered(event, entry: String = "intro") -> void:
EventPlayerContainer.run(event, entry)
func _on_event_trigger_forced(event, entry: String) -> void:
if event == "NONE":
EventPlayerContainer._on_scene_ended()
ChoicePanel.clear_options()
else:
EventPlayerContainer._on_sequence_changed(event, entry)
func _on_masturbated() -> void:
EventPlayerContainer.run("masturbations/init")
func any_menu_open() -> bool:
return InventoryMenu.visible \
or SettingsMenu.visible \
or SaveMenu.visible
1 | # warning-ignore-all:return_value_discarded |
2 | extends HBoxContainer |
3 | class_name ChitinousCanrival |
4 | |
5 | const event_player_scene = preload("res://scenes/ui/EventPlayer.tscn") |
6 | |
7 | @onready var MinigameHandler := %MinigameHandler as MinigameHandler |
8 | @onready var TravelButtons := %TravelButtons as TravelButtons |
9 | @onready var EventPlayerContainer := %EventPlayerContainer as EventPlayerContainer |
10 | @onready var InventoryMenu := %InventoryMenu as InventoryMenu |
11 | @onready var SettingsMenu := %SettingsMenu as SettingsMenu |
12 | @onready var SaveMenu := %SaveMenu as SaveMenu |
13 | @onready var ChoicePanel := %ChoicePanel as Choice |
14 | @onready var StatusPanel := %StatusPanel as StatusPanel |
15 | @onready var Blackout := %BlackoutPanel as BlackoutPanel |
16 | |
17 | var _current_sequence: String = "" |
18 | |
19 | func _ready() -> void: |
20 | randomize() |
21 | |
22 | MusicState.change_bg(MusicState.BACKGROUND_THEME) |
23 | |
24 | ExploreState.set_start_time() |
25 | ExploreState._set_location(SimpleState.state.explore.location) |
26 | TravelButtons.set_button_disabled(SimpleState.state.explore.location) |
27 | |
28 | SaveState.save_loaded.connect(_on_save_loaded) |
29 | EventPlayerContainer.minigame_started.connect(_on_minigame_started) |
30 | MinigameHandler.minigame_finished.connect(_on_minigame_finished) |
31 | |
32 | StatusPanel.inventory_button_toggled.connect(_on_inventory_button_toggled) |
33 | StatusPanel.settings_button_toggled.connect(_on_settings_button_toggled) |
34 | StatusPanel.save_button_toggled.connect(_on_save_button_toggled) |
35 | |
36 | InventoryMenu.visibility_changed.connect(_on_menu_visibility_changed) |
37 | |
38 | SaveMenu.visibility_changed.connect(_on_menu_visibility_changed) |
39 | SaveMenu.closed.connect(StatusPanel.saving_closed) |
40 | |
41 | SettingsMenu.visibility_changed.connect(_on_menu_visibility_changed) |
42 | SettingsMenu.closed.connect(StatusPanel.settings_closed) |
43 | |
44 | TravelButtons.waited.connect(_on_wait_button_pressed) |
45 | |
46 | ChoicePanel.options_shown.connect(_on_options_shown) |
47 | ChoicePanel.options_cleared.connect(_on_options_cleared) |
48 | |
49 | ExploreState.trap_triggered.connect(_on_trap_triggered) |
50 | ExploreState.event_triggered.connect(_on_event_triggered) |
51 | ExploreState.event_trigger_forced.connect(_on_event_trigger_forced) |
52 | ExploreState.revisited.connect(_on_revisited) |
53 | ExploreState.wandered.connect(_on_wandered) |
54 | ExploreState.item_selected.connect(_on_item_selected) |
55 | ExploreState.masturbated.connect(_on_masturbated) |
56 | |
57 | if not MemoryState.has_seen("00-intro/00-premise"): |
58 | InventoryState.add_trap("intro") |
59 | EventPlayerContainer.run("00-intro/00-premise") |
60 | |
61 | if not SimpleState.state.sequence.current_sequence != "None": |
62 | EventPlayerContainer.restore_from_state() |
63 | |
64 | await Blackout.fade_in() |
65 | |
66 | |
67 | func _on_revisited(event: String) -> void: |
68 | EventPlayerContainer.run(event) |
69 | |
70 | |
71 | func _on_wandered(where: String) -> void: |
72 | EventPlayerContainer.run("01-location/%s/wander" % where) |
73 | |
74 | |
75 | func _on_item_selected(what: String) -> void: |
76 | StatusPanel.inventory_closed() |
77 | EventPlayerContainer.run("items/%s" % what) |
78 | |
79 | func _on_save_loaded(title) -> void: |
80 | if not title: |
81 | await Blackout.fade_out() |
82 | |
83 | EventPlayerContainer.hard_stop() |
84 | ChoicePanel.clear_options() |
85 | |
86 | if SimpleState.state.sequence.current_sequence != "NONE": |
87 | EventPlayerContainer.restore_from_state() |
88 | else: |
89 | EventPlayerContainer.hide() |
90 | |
91 | await Blackout.fade_in() |
92 | |
93 | |
94 | func _on_minigame_started(minigame: String, initial_state: Dictionary) -> void: |
95 | MinigameHandler.play_minigame(minigame, initial_state) |
96 | |
97 | |
98 | func _on_minigame_finished(result) -> void: |
99 | EventPlayerContainer.minigame_finished(result) |
100 | |
101 | |
102 | func _on_inventory_button_toggled(pressed: bool) -> void: |
103 | |
104 | InventoryMenu.visible = pressed |
105 | |
106 | if pressed: |
107 | SettingsMenu.visible = false |
108 | StatusPanel.settings_closed() |
109 | |
110 | SaveMenu.visible = false |
111 | StatusPanel.saving_closed() |
112 | |
113 | |
114 | func _on_settings_button_toggled(pressed: bool) -> void: |
115 | SettingsMenu.visible = pressed |
116 | |
117 | if pressed: |
118 | InventoryMenu.visible = false |
119 | StatusPanel.inventory_closed() |
120 | |
121 | SaveMenu.visible = false |
122 | StatusPanel.saving_closed() |
123 | |
124 | |
125 | func _on_save_button_toggled(pressed: bool) -> void: |
126 | SaveMenu.visible = pressed |
127 | |
128 | if pressed: |
129 | InventoryMenu.visible = false |
130 | StatusPanel.inventory_closed() |
131 | |
132 | SettingsMenu.visible = false |
133 | StatusPanel.settings_closed() |
134 | |
135 | |
136 | func _on_menu_visibility_changed() -> void: |
137 | EventPlayerContainer.set_input_disabled(any_menu_open()) |
138 | ChoicePanel.visible = !any_menu_open() and ChoicePanel.active |
139 | |
140 | |
141 | func _on_wait_button_pressed() -> void: |
142 | await Blackout.fade_out() |
143 | ExploreState.wait() |
144 | await Blackout.fade_in() |
145 | |
146 | |
147 | func _on_options_shown() -> void: |
148 | ChoicePanel.visible = !any_menu_open() and ChoicePanel.active |
149 | |
150 | |
151 | func _on_options_cleared() -> void: |
152 | ChoicePanel.hide() |
153 | await get_tree().process_frame |
154 | |
155 | |
156 | func _on_trap_triggered(_trap_name: String, event: String) -> void: |
157 | EventPlayerContainer.run(event) |
158 | |
159 | |
160 | func _on_event_triggered(event, entry: String = "intro") -> void: |
161 | EventPlayerContainer.run(event, entry) |
162 | |
163 | |
164 | func _on_event_trigger_forced(event, entry: String) -> void: |
165 | if event == "NONE": |
166 | EventPlayerContainer._on_scene_ended() |
167 | ChoicePanel.clear_options() |
168 | else: |
169 | EventPlayerContainer._on_sequence_changed(event, entry) |
170 | |
171 | |
172 | func _on_masturbated() -> void: |
173 | EventPlayerContainer.run("masturbations/init") |
174 | |
175 | |
176 | func any_menu_open() -> bool: |
177 | return InventoryMenu.visible \ |
178 | or SettingsMenu.visible \ |
179 | or SaveMenu.visible |
180 |
00_SimpleState.gd
· 1.7 KiB · GDScript3
原始檔案
Playground
extends Node
class_name _SimpleState
signal state_changed(name, state)
var state := { }
func register(state_name: String, inital_state: Dictionary = {}) -> void:
state[state_name] = inital_state
func replace(state_name: String, new_state: Dictionary) -> void:
state[state_name] = new_state.duplicate(true)
emit_signal("state_changed", state_name, state)
func update(state_name: String, new_state: Dictionary) -> void:
state[state_name] = _SimpleState.merge(get_state(state_name), new_state)
emit_signal("state_changed", state_name, state)
func update_deep(state_name: String, new_state: Dictionary) -> void:
state[state_name] = _SimpleState.merge_deep(get_state(state_name), new_state)
emit_signal("state_changed", state_name, state)
func update_mut(state_name: String, new_state: Dictionary) -> void:
_SimpleState.copy_to(state[state_name], new_state)
emit_signal("state_changed")
func _on_update_state(data: Dictionary) -> void:
update(data.state_name, data.state)
func get_state(state_name: String) -> Dictionary:
return state[state_name].duplicate()
static func copy_to(a: Dictionary, b: Dictionary) -> void:
for key in b:
a[key] = b[key]
static func copy_to_deep(a: Dictionary, b: Dictionary) -> void:
for k in b:
if process_recursively(a, b, k):
copy_to_deep(a[k], b[k])
else:
a[k] = b[k]
static func process_recursively(a, b, k) -> bool:
return a.has(k) and a[k] is Dictionary and b[k] is Dictionary
static func merge(a: Dictionary, b: Dictionary) -> Dictionary:
var c := a.duplicate(true)
copy_to(c, b)
return c
static func merge_deep(a: Dictionary, b: Dictionary) -> Dictionary:
var c := a.duplicate(true)
copy_to_deep(c, b)
return c
1 | extends Node |
2 | class_name _SimpleState |
3 | |
4 | signal state_changed(name, state) |
5 | |
6 | var state := { } |
7 | |
8 | |
9 | func register(state_name: String, inital_state: Dictionary = {}) -> void: |
10 | state[state_name] = inital_state |
11 | |
12 | |
13 | func replace(state_name: String, new_state: Dictionary) -> void: |
14 | state[state_name] = new_state.duplicate(true) |
15 | emit_signal("state_changed", state_name, state) |
16 | |
17 | |
18 | func update(state_name: String, new_state: Dictionary) -> void: |
19 | state[state_name] = _SimpleState.merge(get_state(state_name), new_state) |
20 | emit_signal("state_changed", state_name, state) |
21 | |
22 | |
23 | func update_deep(state_name: String, new_state: Dictionary) -> void: |
24 | state[state_name] = _SimpleState.merge_deep(get_state(state_name), new_state) |
25 | emit_signal("state_changed", state_name, state) |
26 | |
27 | |
28 | func update_mut(state_name: String, new_state: Dictionary) -> void: |
29 | _SimpleState.copy_to(state[state_name], new_state) |
30 | emit_signal("state_changed") |
31 | |
32 | |
33 | func _on_update_state(data: Dictionary) -> void: |
34 | update(data.state_name, data.state) |
35 | |
36 | |
37 | func get_state(state_name: String) -> Dictionary: |
38 | return state[state_name].duplicate() |
39 | |
40 | |
41 | static func copy_to(a: Dictionary, b: Dictionary) -> void: |
42 | for key in b: |
43 | a[key] = b[key] |
44 | |
45 | |
46 | |
47 | static func copy_to_deep(a: Dictionary, b: Dictionary) -> void: |
48 | for k in b: |
49 | if process_recursively(a, b, k): |
50 | copy_to_deep(a[k], b[k]) |
51 | else: |
52 | a[k] = b[k] |
53 | |
54 | |
55 | static func process_recursively(a, b, k) -> bool: |
56 | return a.has(k) and a[k] is Dictionary and b[k] is Dictionary |
57 | |
58 | static func merge(a: Dictionary, b: Dictionary) -> Dictionary: |
59 | var c := a.duplicate(true) |
60 | copy_to(c, b) |
61 | return c |
62 | |
63 | |
64 | static func merge_deep(a: Dictionary, b: Dictionary) -> Dictionary: |
65 | var c := a.duplicate(true) |
66 | copy_to_deep(c, b) |
67 | return c |
68 |
01_EventPlayerContainer.gd
· 4.7 KiB · GDScript3
原始檔案
Playground
extends Control
class_name EventPlayerContainer
signal scene_change_finished()
signal sequence_changed(sequence) # warning-ignore:unused_signal
signal options_shown(options)
signal scene_change_started()
signal minigame_started(minigame, initial_state)
const EventPlayerScene = preload("res://scenes/ui/EventPlayer.tscn")
var allow_fade_skip := false
var _event_player_scene : EventPlayer = null
var _changing_scenes := false
func _ready() -> void:
set_input_disabled(true)
SimpleState.state_changed.connect(_on_state_changed) # warning-ignore:return_value_discarded
func _on_state_changed(_name: String, _state: Dictionary) -> void:
pass
func _input(event) -> void:
var mouse_down = event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT
var ui_accept = event.is_action_pressed("ui_accept") and not event.is_echo()
if (mouse_down or ui_accept) and allow_fade_skip:
$FadePanel.skip()
func connect_events(scene) -> void:
# Handled Events
scene.fade_in_started.connect(_on_fade_in_started)
scene.fade_out_started.connect(_on_fade_out_started)
scene.scene_ended.connect(_on_scene_ended)
scene.sequence_changed.connect(_on_sequence_changed)
# Bubbled Events
scene.minigame_started.connect(_on_minigame_started)
func add_to_tree(scene : EventPlayer) -> void:
add_child(scene)
move_child(scene, 0)
func run_scene(scene : EventPlayer, sequence : String, entry : String) -> void:
MemoryState.seen_passage(sequence)
scene.run(sequence, entry)
func restore_scene(scene : EventPlayer, sequence : String, entry : String) -> void:
scene.restore(sequence, entry)
func run(sequence: String, entry: String = "intro") -> void:
_event_player_scene = EventPlayerScene.instantiate()
SimpleState.update("sequence", { current_sequence = sequence, current_line_id = entry })
show()
connect_events(_event_player_scene)
add_to_tree(_event_player_scene)
run_scene(_event_player_scene, sequence, entry)
func restore_from_state() -> void:
var sequence = SimpleState.state.sequence.current_sequence
var entry = SimpleState.state.sequence.current_line_id
_event_player_scene = EventPlayerScene.instantiate()
show()
connect_events(_event_player_scene)
add_to_tree(_event_player_scene)
restore_scene(_event_player_scene, sequence, entry)
func minigame_finished(result) -> void:
if is_instance_valid(_event_player_scene):
_event_player_scene.emit_signal("minigame_finished", result)
func _on_fade_out_started() -> void:
allow_fade_skip = true
if not $FadePanel.fade_shown:
await $FadePanel.fade_out()
if is_instance_valid(_event_player_scene):
_event_player_scene.emit_signal("fade_finished")
else:
_on_fade_out_started()
func _on_fade_in_started() -> void:
if $FadePanel.fade_shown:
await $FadePanel.fade_in()
allow_fade_skip = false
if is_instance_valid(_event_player_scene):
_event_player_scene.emit_signal("fade_finished")
func _on_scene_ended() -> void:
if not _changing_scenes:
stop()
# Bubble Up Events
func _on_minigame_started(minigame: String, initial_state: Dictionary) -> void:
emit_signal("minigame_started", minigame, initial_state)
func _on_sequence_changed(scene: String, line: String = "intro") -> void:
emit_signal("scene_change_started")
_changing_scenes = true
if not $FadePanel.fade_shown:
await $FadePanel.fade_out()
if is_instance_valid(_event_player_scene):
if _event_player_scene.get_parent():
_event_player_scene.get_parent().remove_child(_event_player_scene)
_event_player_scene.queue_free()
run(scene, line)
if $FadePanel.fade_shown:
await $FadePanel.fade_in()
_changing_scenes = false
_event_player_scene.emit_signal("change_scene_finished")
emit_signal("scene_change_finished")
func _options_shown(options: Array) -> void:
emit_signal("options_shown", options)
func stop() -> void:
SimpleState.update("sequence", { current_sequence = "NONE"
, current_line_id = ""
, background = []
, dialogue_pos = "left"
, blackout_visible = false
, dialogue_visible = false
, characters = {}
})
await $FadePanel.fade_out()
if is_instance_valid(_event_player_scene):
if _event_player_scene and _event_player_scene.get_parent():
_event_player_scene.get_parent().remove_child(_event_player_scene)
_event_player_scene.queue_free()
await $FadePanel.fade_in()
hide()
func hard_stop() -> void:
if is_instance_valid(_event_player_scene):
if _event_player_scene and _event_player_scene.get_parent():
_event_player_scene.get_parent().remove_child(_event_player_scene)
_event_player_scene.queue_free()
func set_input_disabled(value: bool) -> void:
if is_instance_valid(_event_player_scene):
_event_player_scene.set_input_disabled(value)
1 | extends Control |
2 | class_name EventPlayerContainer |
3 | |
4 | signal scene_change_finished() |
5 | signal sequence_changed(sequence) # warning-ignore:unused_signal |
6 | signal options_shown(options) |
7 | signal scene_change_started() |
8 | signal minigame_started(minigame, initial_state) |
9 | |
10 | const EventPlayerScene = preload("res://scenes/ui/EventPlayer.tscn") |
11 | |
12 | var allow_fade_skip := false |
13 | |
14 | var _event_player_scene : EventPlayer = null |
15 | var _changing_scenes := false |
16 | |
17 | func _ready() -> void: |
18 | set_input_disabled(true) |
19 | SimpleState.state_changed.connect(_on_state_changed) # warning-ignore:return_value_discarded |
20 | |
21 | |
22 | func _on_state_changed(_name: String, _state: Dictionary) -> void: |
23 | pass |
24 | |
25 | |
26 | func _input(event) -> void: |
27 | var mouse_down = event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT |
28 | var ui_accept = event.is_action_pressed("ui_accept") and not event.is_echo() |
29 | if (mouse_down or ui_accept) and allow_fade_skip: |
30 | $FadePanel.skip() |
31 | |
32 | |
33 | func connect_events(scene) -> void: |
34 | # Handled Events |
35 | scene.fade_in_started.connect(_on_fade_in_started) |
36 | scene.fade_out_started.connect(_on_fade_out_started) |
37 | scene.scene_ended.connect(_on_scene_ended) |
38 | scene.sequence_changed.connect(_on_sequence_changed) |
39 | |
40 | # Bubbled Events |
41 | scene.minigame_started.connect(_on_minigame_started) |
42 | |
43 | |
44 | func add_to_tree(scene : EventPlayer) -> void: |
45 | add_child(scene) |
46 | move_child(scene, 0) |
47 | |
48 | |
49 | func run_scene(scene : EventPlayer, sequence : String, entry : String) -> void: |
50 | MemoryState.seen_passage(sequence) |
51 | scene.run(sequence, entry) |
52 | |
53 | |
54 | func restore_scene(scene : EventPlayer, sequence : String, entry : String) -> void: |
55 | scene.restore(sequence, entry) |
56 | |
57 | |
58 | func run(sequence: String, entry: String = "intro") -> void: |
59 | _event_player_scene = EventPlayerScene.instantiate() |
60 | SimpleState.update("sequence", { current_sequence = sequence, current_line_id = entry }) |
61 | |
62 | show() |
63 | connect_events(_event_player_scene) |
64 | add_to_tree(_event_player_scene) |
65 | run_scene(_event_player_scene, sequence, entry) |
66 | |
67 | |
68 | func restore_from_state() -> void: |
69 | var sequence = SimpleState.state.sequence.current_sequence |
70 | var entry = SimpleState.state.sequence.current_line_id |
71 | _event_player_scene = EventPlayerScene.instantiate() |
72 | |
73 | show() |
74 | connect_events(_event_player_scene) |
75 | add_to_tree(_event_player_scene) |
76 | restore_scene(_event_player_scene, sequence, entry) |
77 | |
78 | |
79 | func minigame_finished(result) -> void: |
80 | if is_instance_valid(_event_player_scene): |
81 | _event_player_scene.emit_signal("minigame_finished", result) |
82 | |
83 | |
84 | func _on_fade_out_started() -> void: |
85 | allow_fade_skip = true |
86 | if not $FadePanel.fade_shown: |
87 | await $FadePanel.fade_out() |
88 | |
89 | if is_instance_valid(_event_player_scene): |
90 | _event_player_scene.emit_signal("fade_finished") |
91 | else: |
92 | _on_fade_out_started() |
93 | |
94 | |
95 | func _on_fade_in_started() -> void: |
96 | if $FadePanel.fade_shown: |
97 | await $FadePanel.fade_in() |
98 | |
99 | |
100 | allow_fade_skip = false |
101 | if is_instance_valid(_event_player_scene): |
102 | _event_player_scene.emit_signal("fade_finished") |
103 | |
104 | |
105 | func _on_scene_ended() -> void: |
106 | if not _changing_scenes: |
107 | stop() |
108 | |
109 | |
110 | # Bubble Up Events |
111 | func _on_minigame_started(minigame: String, initial_state: Dictionary) -> void: |
112 | emit_signal("minigame_started", minigame, initial_state) |
113 | |
114 | |
115 | func _on_sequence_changed(scene: String, line: String = "intro") -> void: |
116 | emit_signal("scene_change_started") |
117 | _changing_scenes = true |
118 | |
119 | if not $FadePanel.fade_shown: |
120 | await $FadePanel.fade_out() |
121 | |
122 | if is_instance_valid(_event_player_scene): |
123 | if _event_player_scene.get_parent(): |
124 | _event_player_scene.get_parent().remove_child(_event_player_scene) |
125 | _event_player_scene.queue_free() |
126 | |
127 | run(scene, line) |
128 | |
129 | if $FadePanel.fade_shown: |
130 | await $FadePanel.fade_in() |
131 | |
132 | _changing_scenes = false |
133 | _event_player_scene.emit_signal("change_scene_finished") |
134 | emit_signal("scene_change_finished") |
135 | |
136 | |
137 | func _options_shown(options: Array) -> void: |
138 | emit_signal("options_shown", options) |
139 | |
140 | |
141 | func stop() -> void: |
142 | SimpleState.update("sequence", { current_sequence = "NONE" |
143 | , current_line_id = "" |
144 | , background = [] |
145 | , dialogue_pos = "left" |
146 | , blackout_visible = false |
147 | , dialogue_visible = false |
148 | , characters = {} |
149 | }) |
150 | await $FadePanel.fade_out() |
151 | |
152 | if is_instance_valid(_event_player_scene): |
153 | if _event_player_scene and _event_player_scene.get_parent(): |
154 | _event_player_scene.get_parent().remove_child(_event_player_scene) |
155 | _event_player_scene.queue_free() |
156 | |
157 | await $FadePanel.fade_in() |
158 | hide() |
159 | |
160 | func hard_stop() -> void: |
161 | if is_instance_valid(_event_player_scene): |
162 | if _event_player_scene and _event_player_scene.get_parent(): |
163 | _event_player_scene.get_parent().remove_child(_event_player_scene) |
164 | _event_player_scene.queue_free() |
165 | |
166 | |
167 | func set_input_disabled(value: bool) -> void: |
168 | if is_instance_valid(_event_player_scene): |
169 | _event_player_scene.set_input_disabled(value) |
170 |
02_EventPlayer.gd
· 5.0 KiB · GDScript3
原始檔案
Playground
extends Control
class_name EventPlayer
# Signal
signal fade_in_started()
signal fade_out_started()
signal scene_ended()
# Proxied Signals
signal minigame_started(minigame : String, initial_state : Dictionary)
signal sequence_changed(sequence : String)
# Signals to Yield on
signal fade_finished() # warning-ignore:unused_signal
signal minigame_finished() # warning-ignore:unused_signal
signal change_scene_finished() # warning-ignore:unused_signal
enum NextFade { FADE_OUT, FADE_IN }
var fade_active = false
var next_fade : NextFade = NextFade.FADE_OUT
@onready var playback : Playback = $Playback
@onready var dialogue_presenter = $DialoguePresenter
@onready var background_presenter = $BackgroundPresenter
@onready var character_handler = $CharacterHandler
@onready var blackout_panel = $BlackoutPanel
@onready var dialogue_box = $DialogueBox
@onready var prize_screen = $PrizeScreen
@onready var choice_panel = get_tree().current_scene.get_node("%MainLayout/%ChoicePanel")
func _ready() -> void:
playback.line_changed.connect(_on_line_changed)
playback.dialogue_shown.connect(_on_dialogue_shown)
playback.options_shown.connect(_on_options_shown)
playback.dialogue_cleared.connect(_on_dialogue_cleared)
playback.scene_finished.connect(_on_scene_finished)
choice_panel.option_picked.connect(_on_option_picked)
playback.extra_game_states = [ self
, dialogue_presenter
, background_presenter
, character_handler
, dialogue_box
, prize_screen
]
# Callbacks
func _on_line_changed(line_id: String) -> void:
SimpleState.update("sequence",
{ current_line_id = line_id })
func _on_dialogue_shown(dialogue_line : DialogueLine) -> void:
if get_parent()._changing_scenes:
await self.change_scene_finished
await dialogue_presenter.show_dialogue(dialogue_line)
playback.dialogue_finished.emit()
func _on_options_shown(options: Array[String]) -> void:
if get_parent()._changing_scenes:
await self.change_scene_finished
choice_panel.show_options(options)
func _on_dialogue_cleared() -> void:
dialogue_presenter.clear_dialogue()
func _on_scene_finished() -> void:
emit_signal("scene_ended")
func _on_options_cleared() -> void:
choice_panel.clear_options()
func _on_option_picked(__, line_id) -> void:
playback.emit_signal("options_picked", line_id)
# Public Methods
func run(sequence: String, entry: String) -> void:
playback.run(Events.items[sequence], entry)
func restore(sequence: String, entry: String) -> void:
var dialogue_pos = SimpleState.state.sequence.dialogue_pos
var background = SimpleState.state.sequence.background
var blackout_visible = SimpleState.state.sequence.blackout_visible
var characters = SimpleState.state.sequence.characters
next_fade = SimpleState.state.sequence.next_fade
dialogue_box.call(dialogue_pos)
background_presenter.background(background)
for character in characters:
character_handler.enter(character, characters[character])
choice_panel.clear_options()
blackout(blackout_visible)
playback.run(Events.items[sequence], entry, true)
func goto(sequence: String) -> void:
sequence_changed.emit(sequence)
await change_scene_finished
func visit_random_minigame() -> void:
var seen = MemoryState.get_seen_minigames()
var unseen = ArrayUtil.difference(CarnivalGames.items.keys(), seen)
var key = ArrayUtil.either(unseen)
var sequence_name = to_squence_name(key)
sequence_changed.emit("minigames/%s/init" % sequence_name)
func to_squence_name(key) -> String:
return key \
.capitalize() \
.replace(" ", "-") \
.to_lower()
func exit() -> void:
await fade_out()
func blackout(visibility: bool) -> void:
SimpleState.update("sequence", { blackout_visible = visibility })
blackout_panel.visible = visibility
func swap_background(layers: Array) -> void:
await fade_out()
await get_tree().process_frame
background_presenter.background(layers)
await fade_in()
func unimplemented() -> void:
assert(false, "Unimplemented Scene")
func play_minigame(minigame: String, initial_state: Dictionary = {}) -> void:
minigame_started.emit(minigame, initial_state)
var result = await self.minigame_finished
SimpleState.update_deep("temp", { values = result })
func fade() -> void:
if fade_active: return
fade_active = true
match next_fade:
NextFade.FADE_OUT:
next_fade = NextFade.FADE_IN
await fade_out()
NextFade.FADE_IN:
next_fade = NextFade.FADE_OUT
await fade_in()
SimpleState.update("sequence", { next_fade = next_fade })
fade_active = false
func fade_out() -> void:
fade_out_started.emit()
await self.fade_finished
func fade_in() -> void:
fade_in_started.emit()
await self.fade_finished
func set_input_disabled(value: bool) -> void:
$Background.input_disabled = value
$Background/SubViewport.gui_disable_input = value
func goto_birth_scene() -> void:
var scene = TempState["parasite"].birthing_scene
ExploreState.emit_signal("event_triggered", scene)
func interaction(background: String) -> void:
set_input_disabled(false)
await background_presenter.start_interaction(background)
set_input_disabled(true)
1 | extends Control |
2 | class_name EventPlayer |
3 | |
4 | # Signal |
5 | signal fade_in_started() |
6 | signal fade_out_started() |
7 | signal scene_ended() |
8 | |
9 | # Proxied Signals |
10 | signal minigame_started(minigame : String, initial_state : Dictionary) |
11 | signal sequence_changed(sequence : String) |
12 | |
13 | # Signals to Yield on |
14 | signal fade_finished() # warning-ignore:unused_signal |
15 | signal minigame_finished() # warning-ignore:unused_signal |
16 | signal change_scene_finished() # warning-ignore:unused_signal |
17 | |
18 | enum NextFade { FADE_OUT, FADE_IN } |
19 | var fade_active = false |
20 | var next_fade : NextFade = NextFade.FADE_OUT |
21 | |
22 | @onready var playback : Playback = $Playback |
23 | @onready var dialogue_presenter = $DialoguePresenter |
24 | @onready var background_presenter = $BackgroundPresenter |
25 | @onready var character_handler = $CharacterHandler |
26 | @onready var blackout_panel = $BlackoutPanel |
27 | @onready var dialogue_box = $DialogueBox |
28 | @onready var prize_screen = $PrizeScreen |
29 | @onready var choice_panel = get_tree().current_scene.get_node("%MainLayout/%ChoicePanel") |
30 | |
31 | func _ready() -> void: |
32 | playback.line_changed.connect(_on_line_changed) |
33 | playback.dialogue_shown.connect(_on_dialogue_shown) |
34 | playback.options_shown.connect(_on_options_shown) |
35 | playback.dialogue_cleared.connect(_on_dialogue_cleared) |
36 | playback.scene_finished.connect(_on_scene_finished) |
37 | choice_panel.option_picked.connect(_on_option_picked) |
38 | |
39 | playback.extra_game_states = [ self |
40 | , dialogue_presenter |
41 | , background_presenter |
42 | , character_handler |
43 | , dialogue_box |
44 | , prize_screen |
45 | ] |
46 | |
47 | |
48 | # Callbacks |
49 | func _on_line_changed(line_id: String) -> void: |
50 | SimpleState.update("sequence", |
51 | { current_line_id = line_id }) |
52 | |
53 | |
54 | func _on_dialogue_shown(dialogue_line : DialogueLine) -> void: |
55 | if get_parent()._changing_scenes: |
56 | await self.change_scene_finished |
57 | |
58 | await dialogue_presenter.show_dialogue(dialogue_line) |
59 | playback.dialogue_finished.emit() |
60 | |
61 | func _on_options_shown(options: Array[String]) -> void: |
62 | if get_parent()._changing_scenes: |
63 | await self.change_scene_finished |
64 | |
65 | choice_panel.show_options(options) |
66 | |
67 | |
68 | func _on_dialogue_cleared() -> void: |
69 | dialogue_presenter.clear_dialogue() |
70 | |
71 | |
72 | func _on_scene_finished() -> void: |
73 | emit_signal("scene_ended") |
74 | |
75 | |
76 | func _on_options_cleared() -> void: |
77 | choice_panel.clear_options() |
78 | |
79 | |
80 | func _on_option_picked(__, line_id) -> void: |
81 | playback.emit_signal("options_picked", line_id) |
82 | |
83 | |
84 | # Public Methods |
85 | func run(sequence: String, entry: String) -> void: |
86 | playback.run(Events.items[sequence], entry) |
87 | |
88 | |
89 | func restore(sequence: String, entry: String) -> void: |
90 | var dialogue_pos = SimpleState.state.sequence.dialogue_pos |
91 | var background = SimpleState.state.sequence.background |
92 | var blackout_visible = SimpleState.state.sequence.blackout_visible |
93 | var characters = SimpleState.state.sequence.characters |
94 | |
95 | next_fade = SimpleState.state.sequence.next_fade |
96 | |
97 | dialogue_box.call(dialogue_pos) |
98 | background_presenter.background(background) |
99 | |
100 | for character in characters: |
101 | character_handler.enter(character, characters[character]) |
102 | |
103 | choice_panel.clear_options() |
104 | blackout(blackout_visible) |
105 | playback.run(Events.items[sequence], entry, true) |
106 | |
107 | |
108 | func goto(sequence: String) -> void: |
109 | sequence_changed.emit(sequence) |
110 | await change_scene_finished |
111 | |
112 | |
113 | func visit_random_minigame() -> void: |
114 | var seen = MemoryState.get_seen_minigames() |
115 | var unseen = ArrayUtil.difference(CarnivalGames.items.keys(), seen) |
116 | var key = ArrayUtil.either(unseen) |
117 | var sequence_name = to_squence_name(key) |
118 | |
119 | sequence_changed.emit("minigames/%s/init" % sequence_name) |
120 | |
121 | |
122 | func to_squence_name(key) -> String: |
123 | return key \ |
124 | .capitalize() \ |
125 | .replace(" ", "-") \ |
126 | .to_lower() |
127 | |
128 | |
129 | func exit() -> void: |
130 | await fade_out() |
131 | |
132 | |
133 | func blackout(visibility: bool) -> void: |
134 | SimpleState.update("sequence", { blackout_visible = visibility }) |
135 | blackout_panel.visible = visibility |
136 | |
137 | |
138 | func swap_background(layers: Array) -> void: |
139 | await fade_out() |
140 | await get_tree().process_frame |
141 | background_presenter.background(layers) |
142 | await fade_in() |
143 | |
144 | |
145 | func unimplemented() -> void: |
146 | assert(false, "Unimplemented Scene") |
147 | |
148 | |
149 | func play_minigame(minigame: String, initial_state: Dictionary = {}) -> void: |
150 | minigame_started.emit(minigame, initial_state) |
151 | var result = await self.minigame_finished |
152 | SimpleState.update_deep("temp", { values = result }) |
153 | |
154 | |
155 | |
156 | func fade() -> void: |
157 | if fade_active: return |
158 | |
159 | fade_active = true |
160 | |
161 | match next_fade: |
162 | NextFade.FADE_OUT: |
163 | next_fade = NextFade.FADE_IN |
164 | await fade_out() |
165 | |
166 | NextFade.FADE_IN: |
167 | next_fade = NextFade.FADE_OUT |
168 | await fade_in() |
169 | |
170 | SimpleState.update("sequence", { next_fade = next_fade }) |
171 | fade_active = false |
172 | |
173 | |
174 | |
175 | func fade_out() -> void: |
176 | fade_out_started.emit() |
177 | await self.fade_finished |
178 | |
179 | |
180 | func fade_in() -> void: |
181 | fade_in_started.emit() |
182 | await self.fade_finished |
183 | |
184 | |
185 | func set_input_disabled(value: bool) -> void: |
186 | $Background.input_disabled = value |
187 | $Background/SubViewport.gui_disable_input = value |
188 | |
189 | |
190 | func goto_birth_scene() -> void: |
191 | var scene = TempState["parasite"].birthing_scene |
192 | ExploreState.emit_signal("event_triggered", scene) |
193 | |
194 | |
195 | func interaction(background: String) -> void: |
196 | set_input_disabled(false) |
197 | await background_presenter.start_interaction(background) |
198 | set_input_disabled(true) |
199 |
03_CharacterHandler.gd
· 3.1 KiB · GDScript3
原始檔案
Playground
extends Node
@export var character_layer_path : NodePath
@export var msg_listener_name = "character_handler"
@onready var character_layer: CanvasLayer = get_node(character_layer_path)
var _characters = {}
var _last_character := ""
func enter(who: String, modifiers: Dictionary = {}) -> void:
if modifiers.has("facing") : match modifiers.facing:
"left" : modifiers.facing = Character.FACING_LEFT
"right" : modifiers.facing = Character.FACING_RIGHT
else:
modifiers.facing = Character.FACING_RIGHT
if modifiers.has("standing") : match modifiers.standing:
"left" : modifiers.standing = Character.STANDING_LEFT
"center": modifiers.standing = Character.STANDING_CENTER
"right" : modifiers.standing = Character.STANDING_RIGHT
else:
modifiers.standing = Character.STANDING_LEFT
if not modifiers.has("current_emote"): modifiers.current_emote = "default"
if not who in _characters:
_characters[who] = Characters.items[who].instantiate()
character_layer.add_child(_characters[who])
for modifier in modifiers:
_characters[who][modifier] = modifiers[modifier]
_last_character = who
SimpleState.update_deep("sequence",
{ characters = { who: modifiers } }
)
func face(face: String, character: String = _last_character) -> void:
assert(face in ["left", "right"]
, "Invalid position %s. Must be 'left' or 'right" % face)
SimpleState.update_deep("sequence",
{ characters = { character: { facing = face } } }
)
if character != _last_character: _last_character = character
var facing: int = Character.STANDING_LEFT
match face:
"left" : facing = Character.FACING_LEFT
"right" : facing = Character.FACING_RIGHT
update(character, "facing", facing)
func stand(stand: String, character: String = _last_character) -> void:
assert(stand in ["left", "center", "right"]
, "Invalid position %s. Must be 'left' or 'center' or 'right" % stand)
SimpleState.update_deep("sequence",
{ characters = { character: { standing = stand } } }
)
if character != _last_character: _last_character = character
var standing: int = Character.STANDING_LEFT
match stand:
"left" : standing = Character.STANDING_LEFT
"center": standing = Character.STANDING_CENTER
"right" : standing = Character.STANDING_RIGHT
update(character, "standing", standing)
func emote(emote: String, character: String = _last_character) -> void:
SimpleState.update_deep("sequence",
{ characters = { character: { current_emote = emote } } }
)
if character != _last_character: _last_character = character
update(character, "current_emote", emote)
func update(who: String, what: String, with) -> void:
_characters[who][what] = with
_last_character = who
func leave(who: String) -> void:
var characters: Dictionary = SimpleState.state.sequence.characters.duplicate()
characters.erase(who) # warning-ignore:return_value_discarded
SimpleState.update("sequence",
{ characters = characters }
)
if who in _characters:
character_layer.remove_child(_characters[who])
_characters[who].queue_free()
_characters.erase(who)
func everyone_leave() -> void:
for who in _characters:
character_layer.remove_child(_characters[who])
1 | extends Node |
2 | |
3 | @export var character_layer_path : NodePath |
4 | @export var msg_listener_name = "character_handler" |
5 | |
6 | @onready var character_layer: CanvasLayer = get_node(character_layer_path) |
7 | |
8 | var _characters = {} |
9 | var _last_character := "" |
10 | |
11 | func enter(who: String, modifiers: Dictionary = {}) -> void: |
12 | if modifiers.has("facing") : match modifiers.facing: |
13 | "left" : modifiers.facing = Character.FACING_LEFT |
14 | "right" : modifiers.facing = Character.FACING_RIGHT |
15 | else: |
16 | modifiers.facing = Character.FACING_RIGHT |
17 | |
18 | if modifiers.has("standing") : match modifiers.standing: |
19 | "left" : modifiers.standing = Character.STANDING_LEFT |
20 | "center": modifiers.standing = Character.STANDING_CENTER |
21 | "right" : modifiers.standing = Character.STANDING_RIGHT |
22 | else: |
23 | modifiers.standing = Character.STANDING_LEFT |
24 | |
25 | if not modifiers.has("current_emote"): modifiers.current_emote = "default" |
26 | |
27 | if not who in _characters: |
28 | _characters[who] = Characters.items[who].instantiate() |
29 | character_layer.add_child(_characters[who]) |
30 | |
31 | |
32 | for modifier in modifiers: |
33 | _characters[who][modifier] = modifiers[modifier] |
34 | |
35 | _last_character = who |
36 | |
37 | SimpleState.update_deep("sequence", |
38 | { characters = { who: modifiers } } |
39 | ) |
40 | |
41 | |
42 | func face(face: String, character: String = _last_character) -> void: |
43 | assert(face in ["left", "right"] |
44 | , "Invalid position %s. Must be 'left' or 'right" % face) |
45 | SimpleState.update_deep("sequence", |
46 | { characters = { character: { facing = face } } } |
47 | ) |
48 | if character != _last_character: _last_character = character |
49 | |
50 | var facing: int = Character.STANDING_LEFT |
51 | match face: |
52 | "left" : facing = Character.FACING_LEFT |
53 | "right" : facing = Character.FACING_RIGHT |
54 | |
55 | update(character, "facing", facing) |
56 | |
57 | |
58 | func stand(stand: String, character: String = _last_character) -> void: |
59 | assert(stand in ["left", "center", "right"] |
60 | , "Invalid position %s. Must be 'left' or 'center' or 'right" % stand) |
61 | |
62 | SimpleState.update_deep("sequence", |
63 | { characters = { character: { standing = stand } } } |
64 | ) |
65 | if character != _last_character: _last_character = character |
66 | |
67 | var standing: int = Character.STANDING_LEFT |
68 | match stand: |
69 | "left" : standing = Character.STANDING_LEFT |
70 | "center": standing = Character.STANDING_CENTER |
71 | "right" : standing = Character.STANDING_RIGHT |
72 | |
73 | update(character, "standing", standing) |
74 | |
75 | |
76 | func emote(emote: String, character: String = _last_character) -> void: |
77 | SimpleState.update_deep("sequence", |
78 | { characters = { character: { current_emote = emote } } } |
79 | ) |
80 | if character != _last_character: _last_character = character |
81 | |
82 | update(character, "current_emote", emote) |
83 | |
84 | |
85 | func update(who: String, what: String, with) -> void: |
86 | _characters[who][what] = with |
87 | _last_character = who |
88 | |
89 | func leave(who: String) -> void: |
90 | var characters: Dictionary = SimpleState.state.sequence.characters.duplicate() |
91 | characters.erase(who) # warning-ignore:return_value_discarded |
92 | SimpleState.update("sequence", |
93 | { characters = characters } |
94 | ) |
95 | |
96 | if who in _characters: |
97 | character_layer.remove_child(_characters[who]) |
98 | _characters[who].queue_free() |
99 | _characters.erase(who) |
100 | |
101 | |
102 | func everyone_leave() -> void: |
103 | for who in _characters: |
104 | character_layer.remove_child(_characters[who]) |
105 |
03_OptionPresenter.gd
· 1.5 KiB · GDScript3
原始檔案
Playground
extends Node
class_name Choice
const ButtonBase = preload("res://scenes/ui/misc/ButtonBase.tscn")
signal options_shown()
signal options_cleared()
signal option_picked(index, line_id)
@export var option_path : NodePath
@export var msg_listener_name = "option_presenter"
var active := false
@onready var options: VBoxContainer = get_node(option_path)
func show_options(option_list: Array) -> void:
assert(len(option_list) % 2 == 0, "Options must be multiples of 2")
var count = min(6, len(option_list))
var buttons = []
for i in range(0, count, 2):
buttons.append(_add_option(option_list[i], option_list[i + 1]))
(buttons[0] as Button).grab_focus()
for i in range(1, len(buttons)):
var top: Button = buttons[i - 1]
var bottom: Button = buttons[i]
bottom.focus_neighbor_top = top.get_path()
top.focus_neighbor_bottom = bottom.get_path()
active = true
emit_signal("options_shown")
func clear_options() -> void:
for child in options.get_children():
options.remove_child(child)
child.queue_free()
active = false
emit_signal("options_cleared")
func _add_option(text: String, line_id: String) -> Button:
var button = ButtonBase.instantiate()
button.focus_mode = Control.FOCUS_ALL
button.text = text
button.connect("pressed", Callable(self, "_on_button_pressed").bind(options.get_child_count(), line_id))
options.add_child(button)
return button
func _on_button_pressed(index: int, line: String) -> void:
clear_options()
emit_signal("option_picked", index, line)
1 | extends Node |
2 | class_name Choice |
3 | const ButtonBase = preload("res://scenes/ui/misc/ButtonBase.tscn") |
4 | |
5 | signal options_shown() |
6 | signal options_cleared() |
7 | signal option_picked(index, line_id) |
8 | |
9 | @export var option_path : NodePath |
10 | @export var msg_listener_name = "option_presenter" |
11 | |
12 | var active := false |
13 | |
14 | @onready var options: VBoxContainer = get_node(option_path) |
15 | |
16 | |
17 | func show_options(option_list: Array) -> void: |
18 | assert(len(option_list) % 2 == 0, "Options must be multiples of 2") |
19 | |
20 | var count = min(6, len(option_list)) |
21 | var buttons = [] |
22 | for i in range(0, count, 2): |
23 | buttons.append(_add_option(option_list[i], option_list[i + 1])) |
24 | |
25 | (buttons[0] as Button).grab_focus() |
26 | for i in range(1, len(buttons)): |
27 | var top: Button = buttons[i - 1] |
28 | var bottom: Button = buttons[i] |
29 | bottom.focus_neighbor_top = top.get_path() |
30 | top.focus_neighbor_bottom = bottom.get_path() |
31 | |
32 | active = true |
33 | emit_signal("options_shown") |
34 | |
35 | |
36 | func clear_options() -> void: |
37 | for child in options.get_children(): |
38 | options.remove_child(child) |
39 | child.queue_free() |
40 | |
41 | active = false |
42 | emit_signal("options_cleared") |
43 | |
44 | |
45 | func _add_option(text: String, line_id: String) -> Button: |
46 | var button = ButtonBase.instantiate() |
47 | button.focus_mode = Control.FOCUS_ALL |
48 | button.text = text |
49 | button.connect("pressed", Callable(self, "_on_button_pressed").bind(options.get_child_count(), line_id)) |
50 | options.add_child(button) |
51 | return button |
52 | |
53 | func _on_button_pressed(index: int, line: String) -> void: |
54 | clear_options() |
55 | emit_signal("option_picked", index, line) |
56 |
03_Playback.gd
· 1.3 KiB · GDScript3
原始檔案
Playground
extends Node
class_name Playback
signal line_changed(line : String)
signal dialogue_shown(dialogue : DialogueLine)
signal options_shown(options : Array[String])
signal dialogue_cleared
signal scene_finished
signal options_picked(line_id : String)
signal dialogue_finished # warning-ignore:unused_signal
var dialogue_line : DialogueLine
var extra_game_states : Array
func run(script : DialogueResource, entry: String = "intro", _restore : bool = false) -> void:
dialogue_line = await DialogueManager.get_next_dialogue_line(script, entry, extra_game_states)
line_changed.emit(entry)
while dialogue_line:
var next_id = dialogue_line.next_id
if not dialogue_line.text.is_empty():
dialogue_shown.emit(dialogue_line)
await self.dialogue_finished
if len(dialogue_line.responses) > 0:
var options : Array[String] = []
for response in dialogue_line.responses:
options.append(response.text)
options.append(response.next_id)
options_shown.emit(options)
next_id = await self.options_picked
else:
var default : Array[String] = [">> Next", ""]
options_shown.emit(default)
await self.options_picked
dialogue_cleared.emit()
line_changed.emit(next_id)
dialogue_line = await DialogueManager.get_next_dialogue_line(script, next_id, extra_game_states)
scene_finished.emit()
1 | extends Node |
2 | class_name Playback |
3 | |
4 | signal line_changed(line : String) |
5 | signal dialogue_shown(dialogue : DialogueLine) |
6 | signal options_shown(options : Array[String]) |
7 | signal dialogue_cleared |
8 | signal scene_finished |
9 | |
10 | signal options_picked(line_id : String) |
11 | signal dialogue_finished # warning-ignore:unused_signal |
12 | |
13 | var dialogue_line : DialogueLine |
14 | var extra_game_states : Array |
15 | |
16 | func run(script : DialogueResource, entry: String = "intro", _restore : bool = false) -> void: |
17 | dialogue_line = await DialogueManager.get_next_dialogue_line(script, entry, extra_game_states) |
18 | |
19 | line_changed.emit(entry) |
20 | while dialogue_line: |
21 | var next_id = dialogue_line.next_id |
22 | |
23 | if not dialogue_line.text.is_empty(): |
24 | dialogue_shown.emit(dialogue_line) |
25 | await self.dialogue_finished |
26 | |
27 | if len(dialogue_line.responses) > 0: |
28 | var options : Array[String] = [] |
29 | |
30 | for response in dialogue_line.responses: |
31 | options.append(response.text) |
32 | options.append(response.next_id) |
33 | |
34 | options_shown.emit(options) |
35 | next_id = await self.options_picked |
36 | |
37 | else: |
38 | var default : Array[String] = [">> Next", ""] |
39 | options_shown.emit(default) |
40 | await self.options_picked |
41 | |
42 | dialogue_cleared.emit() |
43 | line_changed.emit(next_id) |
44 | dialogue_line = await DialogueManager.get_next_dialogue_line(script, next_id, extra_game_states) |
45 | |
46 | scene_finished.emit() |
47 |