Skip to content

Instantly share code, notes, and snippets.

@Capital-EX
Created August 27, 2024 04:21
Show Gist options
  • Save Capital-EX/9d2eaa46fe3465aca4149b5b24f2f2cf to your computer and use it in GitHub Desktop.
Save Capital-EX/9d2eaa46fe3465aca4149b5b24f2f2cf to your computer and use it in GitHub Desktop.
# warning-ignore-all:void_assignment
# warning-ignore-all:return_value_discarded
extends Control
class_name Sequence
# todo - impelement prize screen
signal dialogue_shown()
signal option_pressed(id)
enum Commands {
FADE_OUT, FADE_IN,
CHAR_ENTER, CHAR_MOVE, CHAR_FLIP, CHAR_EXIT, CHAR_EMOTE,
HIDE_DIALOGUE,
APPEND_HISTORY,
WHEN_SEEN, SET_SEEN,
WHEN_FLAG, SET_FLAG,
WHEN, PICK, RUN, GOTO,
AWAIT_RUN, AWAIT_RESULT, AWAIT_SIGNAL,
AWAIT_INTERACTION, AWAIT_MINIGAME,
GIVE_PRIZE, GIVE_ITEM, TAKE_ITEM,
SET_BACKDROP, ADD_BACKDROP, REMOVE_BACKDROP, CLEAR_BACKDROP,
SAY,
# RESPOND is for when the player says something
# NEXT is for when the player needs to click next
# WAIT is for when the player only needs to wait for the dialogue to end
RESPOND, NEXT, WAIT,
CHANGE_STAT, SET_STAT, WHEN_STAT,
CHANGE_MUSIC,
SHOW_BLACKOUT, HIDE_BLACKOUT,
TRANSITION, END
}
enum {
POS_LEFT,
POS_CENTER,
POS_RIGHT,
POS_TOP,
POS_BOTTOM,
}
enum {
FADE_INVISIBLE,
FADE_VISIBLE,
}
const ButtonBase = preload("res://scenes/ui/misc/ButtonBase.tscn")
const ButtonPrize = null
const QMo8_24px = preload("res://fonts/QMo8_24px.tres")
const NoImage = preload("res://imgs/events/NoImage.png")
var entry_passage = "intro"
var entry_line = 0
var entry_previous_state = {}
var opcode = []
var ip = 0
var running = false
var character_lookup = {}
var backdrop_lookup: Dictionary = {}
var skip_fade: bool = false
var fade_state: int = FADE_INVISIBLE
onready var Blackout: ColorRect = $Blackout
onready var BackgroundLayer: CanvasLayer = $SceneContainer/SceneViewport/BackgroundLayer
onready var CharacterLayer: CanvasLayer = $SceneContainer/SceneViewport/CharacterLayer
onready var DialogueContainer: Container = $DialogueContainer
onready var DialogueLabel: Label = $DialogueContainer/MarginContainer/DialogueBox/DialogueMargin/DialogueLabel
onready var OptionsContainer: Container = $MarginContainer/OptionsContainer
onready var ItemScreen: Control = $ItemScreen
onready var FadePlayer: AnimationPlayer = $BlackoutPanel/FadePlayer
onready var DialogueShower: Tween = $DialogueContainer/DailogShower
onready var SceneViewport: Viewport = $SceneContainer/SceneViewport
func set_entry(passage: String, line: int, previous_state: Dictionary) -> void:
prints(passage, line, previous_state)
entry_passage = passage
entry_line = line
entry_previous_state = previous_state
func _ready() -> void:
setup()
execute(entry_passage, entry_line)
func _input(event: InputEvent):
if event is InputEventMouseButton and event.is_pressed() and not event.is_echo():
if DialogueShower.is_active():
DialogueShower.seek(DialogueShower.get_runtime())
if FadePlayer.is_playing():
if FadePlayer.current_animation == "fade_out":
FadePlayer.playback_speed = 1000.0
skip_fade = true
elif FadePlayer.current_animation == "fade_in":
FadePlayer.playback_speed = 1000.0
skip_fade = false
func _exit_tree() -> void:
for character in character_lookup:
character_lookup[character].free()
for backdrop in backdrop_lookup:
backdrop_lookup[backdrop].free()
func _on_option_pressed(id: int) -> void:
$Click.play()
_clear_options()
emit_signal("option_pressed", id)
func setup() -> void:
push_warning("Setup function not overridden.")
func intro() -> void:
push_warning("Missing intro passage.")
func save() -> Dictionary:
var data = {}
for backdrop in backdrop_lookup:
if backdrop_lookup[backdrop].has_method('save') and backdrop_lookup[backdrop].is_ready:
data[backdrop] = backdrop_lookup[backdrop].save()
return data
func execute(entry: String, line: int = 0) -> void:
opcode = []
ip = line
self.call(entry)
State.remember_current_passage(entry)
if ip != 0:
# this must be from an ActionType.RESTORE_STATE
# there exist no op code that results in an IP != 0
# when execute is called.
var current_dialogue = State.fetch_current_dialogue()
var blackout_active = State.fetch_blackout_visible()
var active_backdrop_list = State.fetch_backdrop_list()
var active_character_list = State.fetch_character_list()
if not current_dialogue.empty():
if 'text' in current_dialogue and not current_dialogue.text.empty():
_say(current_dialogue.text, current_dialogue.position, current_dialogue.rate)
DialogueShower.seek(DialogueShower.get_runtime())
if current_dialogue.hidden:
_hide_dialogue()
if blackout_active:
_show_blackout()
for backdrop in active_backdrop_list:
_add_backdrop(backdrop)
for backdrop in entry_previous_state:
prints(backdrop, entry_previous_state[backdrop])
backdrop_lookup[backdrop].set_restore_data(entry_previous_state[backdrop])
for character in active_character_list:
var data = active_character_list[character]
_enter(character, data.standing, data.facing, data.emote)
if opcode[ip].command != Commands.FADE_IN:
$BlackoutPanel.material.set_shader_param('offset', 0)
if not running:
interpret()
func clear() -> void:
for character in character_lookup:
character_lookup[character].free()
for backdrop in backdrop_lookup:
backdrop_lookup[backdrop].free()
func interpret() -> void:
running = true
while ip < len(opcode):
var co: GDScriptFunctionState
var op: Dictionary = opcode[ip]
State.remember_current_line(ip)
ip += 1
co = eval(op)
if co:
yield(co, "completed")
if not opcode[-1].command != Commands.END:
push_warning("Sequence: end() was not called but there are no more instructions to run...")
end()
running = false
func eval(op) -> GDScriptFunctionState:
var co = null
match op.command:
Commands.FADE_IN:
co = _fade_in()
Commands.FADE_OUT:
co = _fade_out()
Commands.CHAR_ENTER:
co = _enter(op.character, op.standing, op.facing, op.emote)
Commands.CHAR_MOVE:
co = _move(op.character, op.standing)
Commands.CHAR_FLIP:
co = _face(op.character, op.facing)
Commands.CHAR_EXIT:
co = _exit(op.character)
Commands.CHAR_EMOTE:
co = _emote(op.character, op.emote)
Commands.HIDE_DIALOGUE:
co = _hide_dialogue()
Commands.APPEND_HISTORY:
co = _append_history(op.history)
Commands.WHEN_SEEN:
co = _when_seen(op.conds)
Commands.SET_SEEN:
co = _set_seen(op.passage)
Commands.WHEN_FLAG:
co = _when_flag(op.conds)
Commands.SET_FLAG:
co = _set_flag(op.flag)
Commands.WHEN:
co = _when(op.conds)
Commands.PICK:
if FADE_VISIBLE: push_warning("Sequencer: fade_out has not been called")
co = _pick(op.options)
Commands.RUN:
co = _run(op.object, op.method, op.args)
Commands.GOTO:
co = _goto(op.passage)
Commands.AWAIT_RUN:
co = _await_run(op. object, op.method, op.args)
Commands.AWAIT_RESULT:
co = _await_result(op.object, op.sig, op.callback, op.handler)
Commands.AWAIT_SIGNAL:
co = _await_signal(op.object, op.sig)
Commands.AWAIT_INTERACTION:
co = _await_interaction(op.id, op.callback, op.sig, op.handler)
Commands.AWAIT_MINIGAME:
co = _await_minigame(op.minigame, op.callback, op.handler)
Commands.GIVE_PRIZE:
co = _give_prize(op.options)
Commands.GIVE_ITEM:
co = _give_item(op.name)
Commands.TAKE_ITEM:
co = _take_item(op.id)
Commands.SET_BACKDROP:
co = _set_backdrop(op.id)
Commands.ADD_BACKDROP:
co = _add_backdrop(op.id)
Commands.REMOVE_BACKDROP:
co = _remove_backdrop(op.id)
Commands.CLEAR_BACKDROP:
co = _clear_backdrop()
Commands.SAY:
if FADE_VISIBLE: push_warning("Sequencer: fade_out has not been called")
co = _say(op.message, op.pos, op.rate)
Commands.RESPOND:
if FADE_VISIBLE: push_warning("Sequencer: fade_out has not been called")
co = _respond(op.message)
Commands.NEXT:
if FADE_VISIBLE: push_warning("Sequencer: fade_out has not been called")
co = _next()
Commands.WAIT:
co = _wait(op.delay)
Commands.CHANGE_STAT:
co = _change_stat(op.stat, op.delta)
Commands.SET_STAT:
co = _set_stat(op.stat, op.value)
Commands.WHEN_STAT:
co = _when_stat(op.conds)
Commands.CHANGE_MUSIC:
co = _change_music(op.track)
Commands.SHOW_BLACKOUT:
co = _show_blackout()
Commands.HIDE_BLACKOUT:
co = _hide_blackout()
Commands.TRANSITION:
co = _transition(op.to)
Commands.END:
co = _end()
return co
func character(character: String) -> void:
character_lookup[character] = Characters.get_character(character)
# ! This will need to be changed to the background loading system
func backdrop_image(id: String, texture: Texture) -> void:
var texture_rect: Sprite = Sprite.new()
texture_rect.centered = false
texture_rect.texture = texture
backdrop_lookup[id] = texture_rect
# ! This will need to be changed to the background loading system
func backdrop_scene(id: String, scene: PackedScene) -> void:
backdrop_lookup[id] = scene.instance()
func get_backdrop(backdrop_name) -> CanvasItem:
return backdrop_lookup.get(backdrop_name)
func fade_out() -> void:
opcode.push_back({
command = Commands.FADE_OUT,
})
func fade_in() -> void:
opcode.push_back({
command = Commands.FADE_IN,
})
func enter(character: String,
standing: int = Character.STANDING_LEFT,
facing: int = Character.FACING_RIGHT,
emote: String = "default") -> void:
opcode.push_back({
command = Commands.CHAR_ENTER,
character = character,
standing = standing,
facing = facing,
emote = emote
})
func move(character: String, standing: int) -> void:
opcode.push_back({
command = Commands.CHAR_MOVE,
character = character,
standing = standing
})
func face(character: String, facing: int) -> void:
opcode.push_back({
command = Commands.CHAR_FLIP,
character = character,
facing = facing,
})
func exit(character: String) -> void:
opcode.push_back({
command = Commands.CHAR_EXIT,
character = character
})
func emote(character: String, emote: String) -> void:
opcode.push_back({
command = Commands.CHAR_EMOTE,
character = character,
emote = emote
})
func hide_dialogue() -> void:
opcode.push_back({
command = Commands.HIDE_DIALOGUE
})
func append_history(history: String) -> void:
opcode.push_back({
command = Commands.APPEND_HISTORY,
history = history
})
func when_seen(conds: Array) -> void:
opcode.push_back({
command = Commands.WHEN_SEEN,
conds = conds
})
func set_seen(passage: String) -> void:
opcode.push_back({
command = Commands.SET_SEEN,
passage = passage
})
func when_flag(conds: Array) -> void:
opcode.push_back({
command = Commands.WHEN_FLAG,
conds = conds
})
func set_flag(flag: String) -> void:
opcode.push_back({
command = Commands.SET_FLAG,
flag = flag
})
func when(conds: Array) -> void:
opcode.push_back({
command = Commands.WHEN_SEEN,
conds = conds
})
func pick(options: Array) -> void:
opcode.push_back({
command = Commands.PICK,
options = options
})
func run(object: Object, method: String, args: Array = []) -> void:
opcode.push_back({
command = Commands.RUN,
object = object,
method = method,
args = args
})
func run_away(object: Object, method: String, args: Array = []) -> void:
opcode.push_back({
command = Commands.WAIT_FOR,
object = object,
method = method,
args = args
})
func goto(passage: String) -> void:
opcode.push_back({
command = Commands.GOTO,
passage = passage
})
# The await_run method is used to wait for a method to complete. This function assumes
# that method returns void. In oreder to wait for a result use await_result.
func await_run(object: Object, method: String, args: Array = []) -> void:
opcode.push_back({
command = Commands.AWAIT_RUN,
object = object,
method = method,
args = args
})
# ! If await_result, await_signal, await_interaction, or await_minigame need to change the story's opcode
# ! then they need to be the last instruction in a passage or call `execute('<passage name>')`. Otherwise,
# ! the instructions they push into the opcode will be executed *after* the remander of the current passage.
# ! However, this could be used to append additional dialogue to the end of the current passage. But, that
# ! may lead to confusion when debugging passages.
# !
# ! Use with cation.
# The await_result method is used to wait for a signal to be emmitted. Additionally, this method allows the
# handler object to receive thee result of the signal. This method should be used to listen for
# the result of any method you want to run.
func await_result(object: Object, sig: String, callback: String, handler: Object = self) -> void:
opcode.push_back({
command = Commands.AWAIT_RESULT,
object = object,
sig = sig,
callback = callback,
handler = handler
})
# The await_signal method will pause the script execution until a specific signal has been emitted.
# This should never be used alone as the story will hang is the signal is never emitted.
func await_signal(object: Object, sig: String) -> void:
opcode.push_back({
command = Commands.AWAIT_SIGNAL,
object = object,
sig = sig
})
# The await_interaction method is used to begin a gameplay sequence in the middle of a story sequence.
# This is short hand for:
# ```gd
# set_backdrop(id)
# run(get_backdrop(id), 'start_interaction')
# await_result(get_backdrop(id), 'interaction_completed', callback, handler)
# ```
# This method *requires* the backdrop specified by the id have the method 'start_interaction'
# and the signal 'interaction_completed' in order to succeed. Additionally, thie method will hang
# the story if 'interaction_completed' is never emitted.
func await_interaction(id: String, callback: String, sig: String = 'interaction_completed', handler: Object = self) -> void:
opcode.push_back({
command = Commands.AWAIT_INTERACTION,
id = id,
callback = callback,
sig = sig,
handler = handler
})
# The await_minigame method starts the specified minigame and then waits for the player to complete it.
# It then passes control to the specified handler.
func await_minigame(minigame: String, callback: String, handler: Object = self) -> void:
opcode.push_back({
command = Commands.AWAIT_MINIGAME,
minigame = minigame,
callback = callback,
handler = handler,
})
func give_prize(options = []) -> void:
opcode.push_back({
command = Commands.GIVE_PRIZE,
options = options
})
func give_item(name: String) -> void:
opcode.push_back({
command = Commands.GIVE_ITEM,
name = name
})
func take_item(id: int) -> void:
opcode.push_back({
command = Commands.TAKE_ITEM,
id = id
})
func set_backdrop(id: String) -> void:
opcode.push_back({
command = Commands.SET_BACKDROP,
id = id
})
func add_backdrop(id: String) -> void:
opcode.push_back({
command = Commands.ADD_BACKDROP,
id = id
})
func remove_backdrop(id: String) -> void:
opcode.push_back({
command= Commands.REMOVE_BACKDROP,
id = id
})
func clear_backdrop() -> void:
opcode.push_back({
command = Commands.CLEAR_BACKDROP
})
func say_left(message: String, rate = 1.0 / 60.0) -> void:
opcode.push_back({
command = Commands.SAY,
pos = POS_LEFT,
message = message,
rate = rate
})
func say_center(message: String, rate = 1.0 / 60.0) -> void:
opcode.push_back({
command = Commands.SAY,
pos = POS_CENTER,
message = message,
rate = rate
})
func say_right(message: String, rate = 1.0 / 60.0) -> void:
opcode.push_back({
command = Commands.SAY,
pos = POS_RIGHT,
message = message,
rate = rate
})
func say_top(message: String, rate = 1.0 / 60.0) -> void:
opcode.push_back({
command = Commands.SAY,
pos = POS_TOP,
message = message,
rate = rate
})
func say_bottom(message: String, rate = 1.0 / 60.0) -> void:
opcode.push_back({
command = Commands.SAY,
pos = POS_BOTTOM,
message = message,
rate = rate
})
func respond(message: String) -> void:
opcode.push_back({
command = Commands.RESPOND,
message = message
})
func next() -> void:
opcode.push_back({
command = Commands.NEXT,
})
func wait(delay: float) -> void:
opcode.push_back({
command = Commands.WAIT,
delay = delay
})
func change_stat(stat: String, delta: int) -> void:
opcode.push_back({
command = Commands.CHANGE_STAT,
stat = stat,
delta = delta
})
func set_stat(stat: String, value: int) -> void:
opcode.push_back({
command = Commands.SET_STAT,
stat = stat,
value = value
})
func when_stat(conds: Array) -> void:
opcode.push_back({
command = Commands.WHEN_STAT,
conds = conds
})
func change_music(track: String) -> void:
opcode.push_back({
command = Commands.CHANGE_MUSIC,
track = track
})
func show_blackout() -> void:
opcode.push_back({
command = Commands.SHOW_BLACKOUT
})
func hide_blackout() -> void:
opcode.push_back({
command = Commands.HIDE_BLACKOUT
})
func transition(to: String) -> void:
opcode.push_back({
command = Commands.TRANSITION,
to = to
})
func end(to: String = Events.NONE) -> void:
opcode.push_back({
command = Commands.END,
to = to
})
# * Private Methods:
func _show_dialogue() -> void:
DialogueContainer.show()
State.remember_dialogue_hidden(false)
func _clear_dialogue() -> void:
DialogueLabel.text = ""
State.forget_current_dialogue()
func _add_option(message: String = "") -> Button:
var button = ButtonBase.instance()
button.text = message
button.size_flags_horizontal = 0
button.add_font_override("font", QMo8_24px)
button.connect("pressed", self, "_on_option_pressed", [OptionsContainer.get_child_count()])
OptionsContainer.add_child(button)
return button
func _clear_options() -> void:
for child in OptionsContainer.get_children():
child.queue_free()
func _fade_out() -> void:
fade_state = FADE_VISIBLE
FadePlayer.play("fade_out")
yield(FadePlayer, "animation_finished")
FadePlayer.playback_speed = 1.0
func _fade_in() -> void:
FadePlayer.play("fade_in")
fade_state = FADE_INVISIBLE
if skip_fade:
FadePlayer.playback_speed = 1000.0
yield(FadePlayer, "animation_finished")
FadePlayer.playback_speed = 1.0
skip_fade = false
func _enter(character: String, standing: int, facing: int, emote: String) -> void:
CharacterLayer.add_child(character_lookup[character])
character_lookup[character].standing = standing
character_lookup[character].facing = facing
character_lookup[character].current_emote = emote
State.remember_character(character, standing, facing, emote)
func _move(character: String, standing: int) -> void:
character_lookup[character].standing = standing
var c = character_lookup[character]
State.remember_character(c, c.standing, c.facing, c.current_emote)
func _face(character: String, facing: int) -> void:
character_lookup[character].facing = facing
var c = character_lookup[character]
State.remember_character(c, c.standing, c.facing, c.current_emote)
func _emote(character: String, emote: String) -> void:
character_lookup[character].current_emote = emote
var c = character_lookup[character]
State.remember_character(c.name, c.standing, c.facing, c.current_emote)
func _exit(character: String) -> void:
CharacterLayer.remove_child(character_lookup[character])
State.forget_character(character)
func _hide_dialogue() -> void:
DialogueContainer.hide()
State.remember_dialogue_hidden(true)
func _append_history(history: String) -> void:
State.append_history(history)
func _when_seen(conds: Array) -> void:
for i in range(0, len(conds), 2):
if State.has_seen(conds[i]):
print(conds[i])
execute(conds[i + 1])
return
execute(conds[-1])
func _set_seen(passage: String) -> void:
State.set_seen(passage)
# TODO - Implement flag system for when a sub-sequence has been seen
func _when_flag(_conds: Array) -> void:
pass
func _set_flag(_flag: String) -> void:
pass
# ! This may be useless with how the interpreter works.
func _when(conds: Array) -> void:
for i in range(0, len(conds), 2):
if conds[i]:
execute(conds[i + 1])
return
execute(conds[-1])
func _pick(options: Array) -> void:
for i in range(0, len(options), 2):
_add_option(options[i])
var id = yield(self, "option_pressed")
_hide_dialogue()
execute(options[id * 2 + 1])
func _run(object: Object, method: String, args: Array = []) -> void:
object.callv(method, args)
func _await_run(object: Object, method: String, args: Array = []) -> void:
var co = object.callv(method, args)
if co is GDScriptFunctionState:
yield(co, "completed")
else:
push_warning("The method %s is not a coroutine. Continuing execution of story." % method)
func _await_result(object: Object, sig: String, callback: String, handler: Object = self) -> void:
object.connect(sig, handler, callback, [], Object.CONNECT_ONESHOT)
yield(object, sig)
func _await_signal(object: Object, sig: String) -> void:
yield(object, sig)
func _await_interaction(id: String, callback: String, sig: String = 'interaction_completed', handler: Object = self) -> void:
var backdrop = backdrop_lookup[id]
State.disable_saving()
# Require to work around quirk where GUI nodes inside a view port will eat the input before
# the outer nodes have a chance to process it
SceneViewport.gui_disable_input = false
_set_backdrop(id)
_run(backdrop, 'start_interaction')
yield(_await_result(backdrop, sig, callback, handler), "completed")
State.enable_saving()
SceneViewport.gui_disable_input = true
func _await_minigame(minigame: String, callback: String, handler: Object = self) -> void:
State.connect('minigame_ended', handler, callback, [], CONNECT_ONESHOT)
State.set_current_minigame(minigame)
func _give_prize(options: Array) -> void:
yield(_fade_out(), 'completed')
ItemScreen.show()
for option in options:
ItemScreen.add_item(option)
yield(_fade_in(), 'completed')
var prize = yield(ItemScreen, 'item_selected')
_give_item(prize)
yield(_fade_out(), "completed")
ItemScreen.hide()
func _give_item(name: String) -> void:
State.add_item(name)
func _take_item(id: int) -> void:
State.remove_item(id)
func _goto(passage: String) -> void:
execute(passage)
func _set_backdrop(backdrop: String) -> void:
_clear_backdrop()
_add_backdrop(backdrop)
func _add_backdrop(backdrop: String) -> void:
BackgroundLayer.add_child(backdrop_lookup[backdrop])
State.remember_backdrop(backdrop)
func _remove_backdrop(backdrop: String) -> void:
var parent = backdrop_lookup[backdrop].get_parent()
if parent:
parent.remove_child(backdrop_lookup[backdrop])
else:
push_warning('The backdrop "%s" is not currently used' % backdrop)
State.forget_backdrop(backdrop)
func _clear_backdrop() -> void:
for child in BackgroundLayer.get_children():
BackgroundLayer.remove_child(child)
State.forget_all_backdrops()
func _clear_characters() -> void:
for child in CharacterLayer.get_children():
CharacterLayer.remove_child(child)
State.forget_all_characters()
func _say(string: String, pos: int = -1, rate = 1.0 / 60.0) -> void:
string = string.dedent().strip_edges()
var count = len(string)
var duration = rate * len(string)
State.remember_current_dialogue(string, pos, rate)
_show_dialogue()
match pos:
POS_LEFT:
position_dialog_left()
POS_CENTER:
position_dialog_center()
POS_RIGHT:
position_dialog_right()
POS_TOP:
position_dialog_top()
POS_BOTTOM:
position_dialog_bottom()
DialogueLabel.text = string
DialogueLabel.visible_characters = 0
DialogueShower.interpolate_property(DialogueLabel, "visible_characters", 0, count, duration)
DialogueShower.start()
yield(DialogueShower, "tween_all_completed")
emit_signal("dialogue_shown")
func _respond(message: String) -> void:
_add_option(message)
yield(self, "option_pressed")
_hide_dialogue()
func _next() -> void:
_add_option(">> Next")
yield(self, "option_pressed")
_hide_dialogue()
func _wait(delay: float) -> void:
yield(get_tree().create_timer(delay), 'timeout')
func _change_stat(stat: String, delta: int) -> void:
State.change_stat(stat, delta)
func _set_stat(stat: String, value: int) -> void:
State.set_stat(stat, value)
func _when_stat(conds: Array) -> void:
for i in range(0, len(conds) - (len(conds) % 4), 4):
var stat: String = conds[i]
var cond: String = conds[i + 1]
var value: int = conds[i + 2]
var method: String = conds[i + 3]
var success: bool = false
match cond:
'<':
success = State.get_stat(stat) < value
'>':
success = State.get_stat(stat) > value
'<=':
success = State.get_stat(stat) <= value
'>=':
success = State.get_stat(stat) >= value
'=', '==':
success = State.get_stat(stat) == value
if success:
execute(method)
return
if len(conds) % 4 == 1:
execute(conds[-1])
elif len(conds) % 4 == 0:
push_warning("Condition array is missing default clause.")
else:
push_warning("Condition array contains incomplete entries.")
func _change_music(track: String) -> void:
State.change_music(track)
func _show_blackout() -> void:
Blackout.show()
State.remember_blackout_visible(true)
func _hide_blackout() -> void:
Blackout.hide()
State.remember_blackout_visible(false)
func _transition(to: String) -> void:
yield(_fade_out(), "completed")
_clear_backdrop()
_clear_characters()
_clear_dialogue()
_clear_options()
_hide_dialogue()
_hide_blackout()
State.set_current_event(to)
func _end() -> void:
yield(_fade_out(), "completed")
_clear_backdrop()
_clear_characters()
_clear_dialogue()
_clear_options()
_hide_dialogue()
_hide_blackout()
_change_music(Music.BACKGROUND_THEME)
yield(_fade_in(), "completed")
State.enable_saving()
State.set_current_event(Events.NONE)
func position_dialog_top() -> void:
DialogueContainer.size_flags_horizontal = Control.SIZE_FILL
DialogueContainer.size_flags_vertical = 0
DialogueLabel.rect_min_size = Vector2(650, 0)
func position_dialog_bottom() -> void:
DialogueContainer.size_flags_horizontal = Control.SIZE_FILL
DialogueContainer.size_flags_vertical = 0
DialogueLabel.rect_min_size = Vector2(650, 0)
func position_dialog_left() -> void:
DialogueContainer.size_flags_horizontal = 0
DialogueContainer.size_flags_vertical = Control.SIZE_FILL
DialogueLabel.rect_min_size = Vector2(250, 0)
func position_dialog_center() -> void:
DialogueContainer.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
DialogueContainer.size_flags_vertical = Control.SIZE_FILL
DialogueLabel.rect_min_size = Vector2(250, 0)
func position_dialog_right() -> void:
DialogueContainer.size_flags_horizontal = Control.SIZE_SHRINK_END
DialogueContainer.size_flags_vertical = Control.SIZE_FILL
DialogueLabel.rect_min_size = Vector2(250, 0)
@carp04
Copy link

carp04 commented Aug 27, 2024

Absolutely insightful breakdown of these GDScript functions! As a student working on my own game development projects, I often found managing dialogues and game states challenging. Thanks to ProgrammingHomeworkHelp. I was able to get clear explanations and step-by-step solutions that made implementing similar functionalities much easier. Their programming homework help service was a game-changer for me, providing the guidance I needed to succeed. If you're struggling with your coding assignments, I highly recommend reaching out to them. You can contact them at +1 (315) 557-6473 or via email at support@programminghomeworkhelp.com. Their support is top-notch and truly helped me excel in my coursework. Keep sharing such valuable content!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment