ajout du détecteur et liaison entre les scènes
This commit is contained in:
@@ -24,18 +24,18 @@ var portrait := ""
|
|||||||
|
|
||||||
## Used to set the character resource from the unique name identifier and vice versa
|
## Used to set the character resource from the unique name identifier and vice versa
|
||||||
var character_identifier: String:
|
var character_identifier: String:
|
||||||
get:
|
get:
|
||||||
if character and not "{" in character_identifier:
|
if character and not "{" in character_identifier:
|
||||||
var identifier := character.get_identifier()
|
var identifier := character.get_identifier()
|
||||||
if not identifier.is_empty():
|
if not identifier.is_empty():
|
||||||
return identifier
|
return identifier
|
||||||
return character_identifier
|
return character_identifier
|
||||||
set(value):
|
set(value):
|
||||||
character_identifier = value
|
character_identifier = value
|
||||||
character = DialogicResourceUtil.get_character_resource(value)
|
character = DialogicResourceUtil.get_character_resource(value)
|
||||||
if Engine.is_editor_hint() and ((not character) or (character and not character.portraits.has(portrait))):
|
if Engine.is_editor_hint() and ((not character) or (character and not character.portraits.has(portrait))):
|
||||||
portrait = ""
|
portrait = ""
|
||||||
ui_update_needed.emit()
|
ui_update_needed.emit()
|
||||||
|
|
||||||
var regex := RegEx.create_from_string(r'\s*((")?(?<name>(?(2)[^"\n]*|[^(: \n]*))(?(2)"|)(\W*(?<portrait>\(.*\)))?\s*(?<!\\):)?(?<text>(.|\n)*)')
|
var regex := RegEx.create_from_string(r'\s*((")?(?<name>(?(2)[^"\n]*|[^(: \n]*))(?(2)"|)(\W*(?<portrait>\(.*\)))?\s*(?<!\\):)?(?<text>(.|\n)*)')
|
||||||
var split_regex := RegEx.create_from_string(r"((\[n\]|\[n\+\])?((?!(\[n\]|\[n\+\]))(.|\n))+)")
|
var split_regex := RegEx.create_from_string(r"((\[n\]|\[n\+\])?((?!(\[n\]|\[n\+\]))(.|\n))+)")
|
||||||
@@ -49,225 +49,225 @@ signal advance
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
func _clear_state() -> void:
|
func _clear_state() -> void:
|
||||||
dialogic.current_state_info.erase('text_sub_idx')
|
dialogic.current_state_info.erase('text_sub_idx')
|
||||||
_disconnect_signals()
|
_disconnect_signals()
|
||||||
|
|
||||||
|
|
||||||
func _execute() -> void:
|
func _execute() -> void:
|
||||||
if text.is_empty():
|
if text.is_empty():
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
|
|
||||||
## If the speaker is provided as an expression, parse it now.
|
## If the speaker is provided as an expression, parse it now.
|
||||||
if "{" in character_identifier:
|
if "{" in character_identifier:
|
||||||
character = null
|
character = null
|
||||||
var character_name: String = dialogic.Expressions.execute_string(character_identifier)
|
var character_name: String = dialogic.Expressions.execute_string(character_identifier)
|
||||||
get_or_create_character(character_name)
|
get_or_create_character(character_name)
|
||||||
|
|
||||||
## Change Portrait and Active Speaker
|
## Change Portrait and Active Speaker
|
||||||
if dialogic.has_subsystem("Portraits"):
|
if dialogic.has_subsystem("Portraits"):
|
||||||
if character:
|
if character:
|
||||||
|
|
||||||
dialogic.Portraits.change_speaker(character, portrait)
|
dialogic.Portraits.change_speaker(character, portrait)
|
||||||
|
|
||||||
if portrait and dialogic.Portraits.is_character_joined(character):
|
if portrait and dialogic.Portraits.is_character_joined(character):
|
||||||
dialogic.Portraits.change_character_portrait(character, portrait)
|
dialogic.Portraits.change_character_portrait(character, portrait)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
dialogic.Portraits.change_speaker(null)
|
dialogic.Portraits.change_speaker(null)
|
||||||
|
|
||||||
## Change and Type Sound Mood
|
## Change and Type Sound Mood
|
||||||
if character:
|
if character:
|
||||||
dialogic.Text.update_name_label(character)
|
dialogic.Text.update_name_label(character)
|
||||||
|
|
||||||
var current_portrait: String = portrait
|
var current_portrait: String = portrait
|
||||||
if portrait.is_empty():
|
if portrait.is_empty():
|
||||||
current_portrait = dialogic.current_state_info["portraits"].get(character.get_identifier(), {}).get("portrait", "")
|
current_portrait = dialogic.current_state_info["portraits"].get(character.get_identifier(), {}).get("portrait", "")
|
||||||
|
|
||||||
var current_portrait_sound_mood: String = character.portraits.get(current_portrait, {}).get("sound_mood", "")
|
var current_portrait_sound_mood: String = character.portraits.get(current_portrait, {}).get("sound_mood", "")
|
||||||
dialogic.Text.update_typing_sound_mood_from_character(character, current_portrait_sound_mood)
|
dialogic.Text.update_typing_sound_mood_from_character(character, current_portrait_sound_mood)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
dialogic.Text.update_name_label(null)
|
dialogic.Text.update_name_label(null)
|
||||||
dialogic.Text.update_typing_sound_mood()
|
dialogic.Text.update_typing_sound_mood()
|
||||||
|
|
||||||
|
|
||||||
## Handle style changes
|
## Handle style changes
|
||||||
if dialogic.has_subsystem("Styles"):
|
if dialogic.has_subsystem("Styles"):
|
||||||
var current_base_style: String = dialogic.current_state_info.get("base_style")
|
var current_base_style: String = dialogic.current_state_info.get("base_style")
|
||||||
var current_style: String = dialogic.current_state_info.get("style", "")
|
var current_style: String = dialogic.current_state_info.get("style", "")
|
||||||
var character_style: String = "" if not character else character.custom_info.get("style", "")
|
var character_style: String = "" if not character else character.custom_info.get("style", "")
|
||||||
|
|
||||||
## Change back to base style, if another characters style is currently used
|
## Change back to base style, if another characters style is currently used
|
||||||
if (not character or character_style.is_empty()) and (current_base_style != current_style):
|
if (not character or character_style.is_empty()) and (current_base_style != current_style):
|
||||||
dialogic.Styles.change_style(dialogic.current_state_info.get("base_style", "Default"))
|
dialogic.Styles.change_style(dialogic.current_state_info.get("base_style", "Default"))
|
||||||
await dialogic.get_tree().process_frame
|
await dialogic.get_tree().process_frame
|
||||||
|
|
||||||
## Change to the characters style if this character has one
|
## Change to the characters style if this character has one
|
||||||
elif character and not character_style.is_empty():
|
elif character and not character_style.is_empty():
|
||||||
dialogic.Styles.change_style(character_style, false)
|
dialogic.Styles.change_style(character_style, false)
|
||||||
await dialogic.get_tree().process_frame
|
await dialogic.get_tree().process_frame
|
||||||
|
|
||||||
_connect_signals()
|
_connect_signals()
|
||||||
|
|
||||||
var character_name_text := dialogic.Text.get_character_name_parsed(character)
|
var character_name_text := dialogic.Text.get_character_name_parsed(character)
|
||||||
var final_text: String = get_property_translated('text')
|
var final_text: String = get_property_translated('text')
|
||||||
if ProjectSettings.get_setting('dialogic/text/split_at_new_lines', false):
|
if ProjectSettings.get_setting('dialogic/text/split_at_new_lines', false):
|
||||||
match ProjectSettings.get_setting('dialogic/text/split_at_new_lines_as', 0):
|
match ProjectSettings.get_setting('dialogic/text/split_at_new_lines_as', 0):
|
||||||
0:
|
0:
|
||||||
final_text = final_text.replace('\n', '[n]')
|
final_text = final_text.replace('\n', '[n]')
|
||||||
1:
|
1:
|
||||||
final_text = final_text.replace('\n', '[n+][br]')
|
final_text = final_text.replace('\n', '[n+][br]')
|
||||||
|
|
||||||
var split_text := []
|
var split_text := []
|
||||||
for i in split_regex.search_all(final_text):
|
for i in split_regex.search_all(final_text):
|
||||||
split_text.append([i.get_string().trim_prefix('[n]').trim_prefix('[n+]')])
|
split_text.append([i.get_string().trim_prefix('[n]').trim_prefix('[n+]')])
|
||||||
split_text[-1].append(i.get_string().begins_with('[n+]'))
|
split_text[-1].append(i.get_string().begins_with('[n+]'))
|
||||||
|
|
||||||
dialogic.current_state_info['text_sub_idx'] = dialogic.current_state_info.get('text_sub_idx', -1)
|
dialogic.current_state_info['text_sub_idx'] = dialogic.current_state_info.get('text_sub_idx', -1)
|
||||||
|
|
||||||
var reveal_next_segment: bool = dialogic.current_state_info['text_sub_idx'] == -1
|
var reveal_next_segment: bool = dialogic.current_state_info['text_sub_idx'] == -1
|
||||||
|
|
||||||
for section_idx in range(min(max(0, dialogic.current_state_info['text_sub_idx']), len(split_text)-1), len(split_text)):
|
for section_idx in range(min(max(0, dialogic.current_state_info['text_sub_idx']), len(split_text)-1), len(split_text)):
|
||||||
dialogic.Inputs.block_input(ProjectSettings.get_setting('dialogic/text/text_reveal_skip_delay', 0.1))
|
dialogic.Inputs.block_input(ProjectSettings.get_setting('dialogic/text/text_reveal_skip_delay', 0.1))
|
||||||
|
|
||||||
if reveal_next_segment:
|
if reveal_next_segment:
|
||||||
dialogic.Text.hide_next_indicators()
|
dialogic.Text.hide_next_indicators()
|
||||||
|
|
||||||
dialogic.current_state_info['text_sub_idx'] = section_idx
|
dialogic.current_state_info['text_sub_idx'] = section_idx
|
||||||
|
|
||||||
var segment: String = dialogic.Text.parse_text(split_text[section_idx][0], 0)
|
var segment: String = dialogic.Text.parse_text(split_text[section_idx][0], 0)
|
||||||
var is_append: bool = split_text[section_idx][1]
|
var is_append: bool = split_text[section_idx][1]
|
||||||
|
|
||||||
final_text = ProjectSettings.get_setting("dialogic/text/dialog_text_prefix", "")+segment
|
final_text = ProjectSettings.get_setting("dialogic/text/dialog_text_prefix", "")+segment
|
||||||
dialogic.Text.about_to_show_text.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append})
|
dialogic.Text.about_to_show_text.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append})
|
||||||
|
|
||||||
await dialogic.Text.update_textbox(final_text, false)
|
await dialogic.Text.update_textbox(final_text, false)
|
||||||
|
|
||||||
state = States.REVEALING
|
state = States.REVEALING
|
||||||
_try_play_current_line_voice()
|
_try_play_current_line_voice()
|
||||||
final_text = dialogic.Text.update_dialog_text(final_text, false, is_append)
|
final_text = dialogic.Text.update_dialog_text(final_text, false, is_append)
|
||||||
|
|
||||||
dialogic.Text.text_started.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append})
|
dialogic.Text.text_started.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append})
|
||||||
|
|
||||||
_mark_as_read(character_name_text, final_text)
|
_mark_as_read(character_name_text, final_text)
|
||||||
|
|
||||||
# We must skip text animation before we potentially return when there
|
# We must skip text animation before we potentially return when there
|
||||||
# is a Choice event.
|
# is a Choice event.
|
||||||
if dialogic.Inputs.auto_skip.enabled:
|
if dialogic.Inputs.auto_skip.enabled:
|
||||||
dialogic.Text.skip_text_reveal()
|
dialogic.Text.skip_text_reveal()
|
||||||
else:
|
else:
|
||||||
await dialogic.Text.text_finished
|
await dialogic.Text.text_finished
|
||||||
|
|
||||||
state = States.IDLE
|
state = States.IDLE
|
||||||
else:
|
else:
|
||||||
reveal_next_segment = true
|
reveal_next_segment = true
|
||||||
|
|
||||||
# Handling potential Choice Events.
|
# Handling potential Choice Events.
|
||||||
if section_idx == len(split_text)-1 and dialogic.has_subsystem('Choices') and dialogic.Choices.is_question(dialogic.current_event_idx):
|
if section_idx == len(split_text)-1 and dialogic.has_subsystem('Choices') and dialogic.Choices.is_question(dialogic.current_event_idx):
|
||||||
dialogic.Text.show_next_indicators(true)
|
dialogic.Text.show_next_indicators(true)
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
|
|
||||||
elif dialogic.Inputs.auto_advance.is_enabled():
|
elif dialogic.Inputs.auto_advance.is_enabled():
|
||||||
dialogic.Text.show_next_indicators(false, true)
|
dialogic.Text.show_next_indicators(false, true)
|
||||||
dialogic.Inputs.auto_advance.start()
|
dialogic.Inputs.auto_advance.start()
|
||||||
else:
|
else:
|
||||||
dialogic.Text.show_next_indicators()
|
dialogic.Text.show_next_indicators()
|
||||||
|
|
||||||
if section_idx == len(split_text)-1:
|
if section_idx == len(split_text)-1:
|
||||||
state = States.DONE
|
state = States.DONE
|
||||||
|
|
||||||
# If Auto-Skip is enabled and there are multiple parts of this text
|
# If Auto-Skip is enabled and there are multiple parts of this text
|
||||||
# we need to skip the text after the defined time per event.
|
# we need to skip the text after the defined time per event.
|
||||||
if dialogic.Inputs.auto_skip.enabled:
|
if dialogic.Inputs.auto_skip.enabled:
|
||||||
await dialogic.Inputs.start_autoskip_timer()
|
await dialogic.Inputs.start_autoskip_timer()
|
||||||
|
|
||||||
# Check if Auto-Skip is still enabled.
|
# Check if Auto-Skip is still enabled.
|
||||||
if not dialogic.Inputs.auto_skip.enabled:
|
if not dialogic.Inputs.auto_skip.enabled:
|
||||||
await advance
|
await advance
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await advance
|
await advance
|
||||||
|
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
|
|
||||||
|
|
||||||
func _mark_as_read(character_name_text: String, final_text: String) -> void:
|
func _mark_as_read(character_name_text: String, final_text: String) -> void:
|
||||||
if dialogic.has_subsystem('History'):
|
if dialogic.has_subsystem('History'):
|
||||||
if character:
|
if character:
|
||||||
dialogic.History.store_simple_history_entry(final_text, event_name, {'character':character_name_text, 'character_color':character.color})
|
dialogic.History.store_simple_history_entry(final_text, event_name, {'character':character_name_text, 'character_color':character.color})
|
||||||
else:
|
else:
|
||||||
dialogic.History.store_simple_history_entry(final_text, event_name)
|
dialogic.History.store_simple_history_entry(final_text, event_name)
|
||||||
dialogic.History.mark_event_as_visited()
|
dialogic.History.mark_event_as_visited()
|
||||||
|
|
||||||
|
|
||||||
func _connect_signals() -> void:
|
func _connect_signals() -> void:
|
||||||
if not dialogic.Inputs.dialogic_action.is_connected(_on_dialogic_input_action):
|
if not dialogic.Inputs.dialogic_action.is_connected(_on_dialogic_input_action):
|
||||||
dialogic.Inputs.dialogic_action.connect(_on_dialogic_input_action)
|
dialogic.Inputs.dialogic_action.connect(_on_dialogic_input_action)
|
||||||
|
|
||||||
dialogic.Inputs.auto_skip.toggled.connect(_on_auto_skip_enable)
|
dialogic.Inputs.auto_skip.toggled.connect(_on_auto_skip_enable)
|
||||||
|
|
||||||
if not dialogic.Inputs.auto_advance.autoadvance.is_connected(_on_dialogic_input_autoadvance):
|
if not dialogic.Inputs.auto_advance.autoadvance.is_connected(_on_dialogic_input_autoadvance):
|
||||||
dialogic.Inputs.auto_advance.autoadvance.connect(_on_dialogic_input_autoadvance)
|
dialogic.Inputs.auto_advance.autoadvance.connect(_on_dialogic_input_autoadvance)
|
||||||
|
|
||||||
|
|
||||||
## If the event is done, this method can clean-up signal connections.
|
## If the event is done, this method can clean-up signal connections.
|
||||||
func _disconnect_signals() -> void:
|
func _disconnect_signals() -> void:
|
||||||
if dialogic.Inputs.dialogic_action.is_connected(_on_dialogic_input_action):
|
if dialogic.Inputs.dialogic_action.is_connected(_on_dialogic_input_action):
|
||||||
dialogic.Inputs.dialogic_action.disconnect(_on_dialogic_input_action)
|
dialogic.Inputs.dialogic_action.disconnect(_on_dialogic_input_action)
|
||||||
if dialogic.Inputs.auto_advance.autoadvance.is_connected(_on_dialogic_input_autoadvance):
|
if dialogic.Inputs.auto_advance.autoadvance.is_connected(_on_dialogic_input_autoadvance):
|
||||||
dialogic.Inputs.auto_advance.autoadvance.disconnect(_on_dialogic_input_autoadvance)
|
dialogic.Inputs.auto_advance.autoadvance.disconnect(_on_dialogic_input_autoadvance)
|
||||||
if dialogic.Inputs.auto_skip.toggled.is_connected(_on_auto_skip_enable):
|
if dialogic.Inputs.auto_skip.toggled.is_connected(_on_auto_skip_enable):
|
||||||
dialogic.Inputs.auto_skip.toggled.disconnect(_on_auto_skip_enable)
|
dialogic.Inputs.auto_skip.toggled.disconnect(_on_auto_skip_enable)
|
||||||
|
|
||||||
|
|
||||||
## Tries to play the voice clip for the current line.
|
## Tries to play the voice clip for the current line.
|
||||||
func _try_play_current_line_voice() -> void:
|
func _try_play_current_line_voice() -> void:
|
||||||
# If Auto-Skip is enabled and we skip voice clips, we don't want to play.
|
# If Auto-Skip is enabled and we skip voice clips, we don't want to play.
|
||||||
if (dialogic.Inputs.auto_skip.enabled
|
if (dialogic.Inputs.auto_skip.enabled
|
||||||
and dialogic.Inputs.auto_skip.skip_voice):
|
and dialogic.Inputs.auto_skip.skip_voice):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Plays the audio region for the current line.
|
# Plays the audio region for the current line.
|
||||||
if (dialogic.has_subsystem('Voice')
|
if (dialogic.has_subsystem('Voice')
|
||||||
and dialogic.Voice.is_voiced(dialogic.current_event_idx)):
|
and dialogic.Voice.is_voiced(dialogic.current_event_idx)):
|
||||||
dialogic.Voice.play_voice()
|
dialogic.Voice.play_voice()
|
||||||
|
|
||||||
|
|
||||||
func _on_dialogic_input_action() -> void:
|
func _on_dialogic_input_action() -> void:
|
||||||
match state:
|
match state:
|
||||||
States.REVEALING:
|
States.REVEALING:
|
||||||
if dialogic.Text.is_text_reveal_skippable():
|
if dialogic.Text.is_text_reveal_skippable():
|
||||||
dialogic.Text.skip_text_reveal()
|
dialogic.Text.skip_text_reveal()
|
||||||
dialogic.Inputs.stop_timers()
|
dialogic.Inputs.stop_timers()
|
||||||
_:
|
_:
|
||||||
if dialogic.Inputs.manual_advance.is_enabled():
|
if dialogic.Inputs.manual_advance.is_enabled():
|
||||||
advance.emit()
|
advance.emit()
|
||||||
dialogic.Inputs.stop_timers()
|
dialogic.Inputs.stop_timers()
|
||||||
|
|
||||||
|
|
||||||
func _on_dialogic_input_autoadvance() -> void:
|
func _on_dialogic_input_autoadvance() -> void:
|
||||||
if state == States.IDLE or state == States.DONE:
|
if state == States.IDLE or state == States.DONE:
|
||||||
advance.emit()
|
advance.emit()
|
||||||
|
|
||||||
|
|
||||||
func _on_auto_skip_enable(enabled: bool) -> void:
|
func _on_auto_skip_enable(enabled: bool) -> void:
|
||||||
if not enabled:
|
if not enabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
match state:
|
match state:
|
||||||
States.DONE:
|
States.DONE:
|
||||||
await dialogic.Inputs.start_autoskip_timer()
|
await dialogic.Inputs.start_autoskip_timer()
|
||||||
|
|
||||||
# If Auto-Skip is still enabled, advance the text.
|
# If Auto-Skip is still enabled, advance the text.
|
||||||
if dialogic.Inputs.auto_skip.enabled:
|
if dialogic.Inputs.auto_skip.enabled:
|
||||||
advance.emit()
|
advance.emit()
|
||||||
|
|
||||||
States.REVEALING:
|
States.REVEALING:
|
||||||
dialogic.Text.skip_text_reveal()
|
dialogic.Text.skip_text_reveal()
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -276,12 +276,12 @@ func _on_auto_skip_enable(enabled: bool) -> void:
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
event_name = "Text"
|
event_name = "Text"
|
||||||
set_default_color('Color1')
|
set_default_color('Color1')
|
||||||
event_category = "Main"
|
event_category = "Main"
|
||||||
event_sorting_index = 0
|
event_sorting_index = 0
|
||||||
expand_by_default = true
|
expand_by_default = true
|
||||||
help_page_path = "https://docs.dialogic.pro/writing-texts.html"
|
help_page_path = "https://docs.dialogic.pro/writing-texts.html"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -289,92 +289,92 @@ func _init() -> void:
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
func to_text() -> String:
|
func to_text() -> String:
|
||||||
var result := text.replace('\n', '\\\n').strip_edges(false).trim_suffix("\\")
|
var result := text.replace('\n', '\\\n').strip_edges(false).trim_suffix("\\")
|
||||||
result = result.replace(':', '\\:')
|
result = result.replace(':', '\\:')
|
||||||
if result.is_empty():
|
if result.is_empty():
|
||||||
result = "<Empty Text Event>"
|
result = "<Empty Text Event>"
|
||||||
|
|
||||||
if character or character_identifier:
|
if character or character_identifier:
|
||||||
var name := character_identifier
|
var name := character_identifier
|
||||||
if character:
|
if character:
|
||||||
name = character.get_identifier()
|
name = character.get_identifier()
|
||||||
if name.count(" ") > 0:
|
if name.count(" ") > 0:
|
||||||
name = '"' + name + '"'
|
name = '"' + name + '"'
|
||||||
if not portrait.is_empty():
|
if not portrait.is_empty():
|
||||||
result = name+" ("+portrait+"): "+result
|
result = name+" ("+portrait+"): "+result
|
||||||
else:
|
else:
|
||||||
result = name+": "+result
|
result = name+": "+result
|
||||||
for event in DialogicResourceUtil.get_event_cache():
|
for event in DialogicResourceUtil.get_event_cache():
|
||||||
if not event is DialogicTextEvent and event.is_valid_event(result):
|
if not event is DialogicTextEvent and event.is_valid_event(result):
|
||||||
result = '\\'+result
|
result = '\\'+result
|
||||||
break
|
break
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
func from_text(string:String) -> void:
|
func from_text(string:String) -> void:
|
||||||
# Load default character
|
# Load default character
|
||||||
# This is only of relevance if the default has been overriden (usually not)
|
# This is only of relevance if the default has been overriden (usually not)
|
||||||
character = DialogicResourceUtil.get_character_resource(character_identifier)
|
character = DialogicResourceUtil.get_character_resource(character_identifier)
|
||||||
|
|
||||||
var result := regex.search(string.trim_prefix('\\'))
|
var result := regex.search(string.trim_prefix('\\'))
|
||||||
|
|
||||||
if result.get_string('portrait'):
|
if result.get_string('portrait'):
|
||||||
portrait = result.get_string('portrait').strip_edges().trim_prefix('(').trim_suffix(')')
|
portrait = result.get_string('portrait').strip_edges().trim_prefix('(').trim_suffix(')')
|
||||||
|
|
||||||
if result and not result.get_string('name').is_empty():
|
if result and not result.get_string('name').is_empty():
|
||||||
var name := result.get_string('name').strip_edges()
|
var name := result.get_string('name').strip_edges()
|
||||||
|
|
||||||
if name == '_':
|
if name == '_':
|
||||||
character = null
|
character = null
|
||||||
elif "{" in name:
|
elif "{" in name:
|
||||||
## If it's an expression, we load the character in _execute.
|
## If it's an expression, we load the character in _execute.
|
||||||
character_identifier = name
|
character_identifier = name
|
||||||
character = null
|
character = null
|
||||||
else:
|
else:
|
||||||
get_or_create_character(name)
|
get_or_create_character(name)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return
|
return
|
||||||
|
|
||||||
text = result.get_string('text').replace("\\\n", "\n").replace('\\:', ':').strip_edges().trim_prefix('\\')
|
text = result.get_string('text').replace("\\\n", "\n").replace('\\:', ':').strip_edges().trim_prefix('\\')
|
||||||
if text == '<Empty Text Event>':
|
if text == '<Empty Text Event>':
|
||||||
text = ""
|
text = ""
|
||||||
|
|
||||||
|
|
||||||
func get_or_create_character(name:String) -> void:
|
func get_or_create_character(name:String) -> void:
|
||||||
character = DialogicResourceUtil.get_character_resource(name)
|
character = DialogicResourceUtil.get_character_resource(name)
|
||||||
|
|
||||||
if character == null:
|
if character == null:
|
||||||
if Engine.is_editor_hint() == false:
|
if Engine.is_editor_hint() == false:
|
||||||
character = DialogicCharacter.new()
|
character = DialogicCharacter.new()
|
||||||
character.display_name = name
|
character.display_name = name
|
||||||
character.set_identifier(name)
|
character.set_identifier(name)
|
||||||
if portrait:
|
if portrait:
|
||||||
if "{" in portrait:
|
if "{" in portrait:
|
||||||
character.color = Color(dialogic.Expressions.execute_string(portrait))
|
character.color = Color(dialogic.Expressions.execute_string(portrait))
|
||||||
else:
|
else:
|
||||||
character.color = Color(portrait)
|
character.color = Color(portrait)
|
||||||
else:
|
else:
|
||||||
character_identifier = name
|
character_identifier = name
|
||||||
|
|
||||||
|
|
||||||
func is_valid_event(_string:String) -> bool:
|
func is_valid_event(_string:String) -> bool:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
func is_string_full_event(string:String) -> bool:
|
func is_string_full_event(string:String) -> bool:
|
||||||
return !string.ends_with('\\')
|
return !string.ends_with('\\')
|
||||||
|
|
||||||
|
|
||||||
# this is only here to provide a list of default values
|
# this is only here to provide a list of default values
|
||||||
# this way the module manager can add custom default overrides to this event.
|
# this way the module manager can add custom default overrides to this event.
|
||||||
func get_shortcode_parameters() -> Dictionary:
|
func get_shortcode_parameters() -> Dictionary:
|
||||||
return {
|
return {
|
||||||
#param_name : property_info
|
#param_name : property_info
|
||||||
"character" : {"property": "character_identifier", "default": "", "ext_file":true},
|
"character" : {"property": "character_identifier", "default": "", "ext_file":true},
|
||||||
"portrait" : {"property": "portrait", "default": ""},
|
"portrait" : {"property": "portrait", "default": ""},
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -382,14 +382,14 @@ func get_shortcode_parameters() -> Dictionary:
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
func _get_translatable_properties() -> Array:
|
func _get_translatable_properties() -> Array:
|
||||||
return ['text']
|
return ['text']
|
||||||
|
|
||||||
|
|
||||||
func _get_property_original_translation(property:String) -> String:
|
func _get_property_original_translation(property:String) -> String:
|
||||||
match property:
|
match property:
|
||||||
'text':
|
'text':
|
||||||
return text
|
return text
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -399,44 +399,44 @@ func _get_property_original_translation(property:String) -> String:
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
func _enter_visual_editor(editor:DialogicEditor):
|
func _enter_visual_editor(editor:DialogicEditor):
|
||||||
editor.opened.connect(func(): ui_update_needed.emit())
|
editor.opened.connect(func(): ui_update_needed.emit())
|
||||||
|
|
||||||
|
|
||||||
func build_event_editor() -> void:
|
func build_event_editor() -> void:
|
||||||
add_header_edit('character_identifier', ValueType.DYNAMIC_OPTIONS,
|
add_header_edit('character_identifier', ValueType.DYNAMIC_OPTIONS,
|
||||||
{'file_extension' : '.dch',
|
{'file_extension' : '.dch',
|
||||||
'mode' : 2,
|
'mode' : 2,
|
||||||
'suggestions_func' : get_character_suggestions,
|
'suggestions_func' : get_character_suggestions,
|
||||||
'placeholder' : '(No one)',
|
'placeholder' : '(No one)',
|
||||||
'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg")}, 'do_any_characters_exist()')
|
'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg")}, 'do_any_characters_exist()')
|
||||||
add_header_edit('portrait', ValueType.DYNAMIC_OPTIONS,
|
add_header_edit('portrait', ValueType.DYNAMIC_OPTIONS,
|
||||||
{'suggestions_func' : get_portrait_suggestions,
|
{'suggestions_func' : get_portrait_suggestions,
|
||||||
'placeholder' : "(Don't change)",
|
'placeholder' : "(Don't change)",
|
||||||
'icon' : load("res://addons/dialogic/Editor/Images/Resources/portrait.svg"),
|
'icon' : load("res://addons/dialogic/Editor/Images/Resources/portrait.svg"),
|
||||||
'collapse_when_empty': true,},
|
'collapse_when_empty': true,},
|
||||||
'should_show_portrait_selector()')
|
'should_show_portrait_selector()')
|
||||||
add_body_edit('text', ValueType.MULTILINE_TEXT, {'autofocus':true})
|
add_body_edit('text', ValueType.MULTILINE_TEXT, {'autofocus':true})
|
||||||
|
|
||||||
|
|
||||||
func should_show_portrait_selector() -> bool:
|
func should_show_portrait_selector() -> bool:
|
||||||
return character and not character.portraits.is_empty() and not character.portraits.size() == 1
|
return character and not character.portraits.is_empty() and not character.portraits.size() == 1
|
||||||
|
|
||||||
|
|
||||||
func do_any_characters_exist() -> bool:
|
func do_any_characters_exist() -> bool:
|
||||||
return not DialogicResourceUtil.get_character_directory().is_empty()
|
return not DialogicResourceUtil.get_character_directory().is_empty()
|
||||||
|
|
||||||
|
|
||||||
func get_character_suggestions(search_text:String) -> Dictionary:
|
func get_character_suggestions(search_text:String) -> Dictionary:
|
||||||
var suggestions := DialogicUtil.get_character_suggestions(search_text, character, true, false, editor_node)
|
var suggestions := DialogicUtil.get_character_suggestions(search_text, character, true, false, editor_node)
|
||||||
if search_text and not search_text in suggestions:
|
if search_text and not search_text in suggestions:
|
||||||
suggestions[search_text] = {
|
suggestions[search_text] = {
|
||||||
"value":search_text,
|
"value":search_text,
|
||||||
"tooltip": "A temporary character, created on the spot.",
|
"tooltip": "A temporary character, created on the spot.",
|
||||||
"editor_icon":["GuiEllipsis", "EditorIcons"]}
|
"editor_icon":["GuiEllipsis", "EditorIcons"]}
|
||||||
return suggestions
|
return suggestions
|
||||||
|
|
||||||
func get_portrait_suggestions(search_text:String) -> Dictionary:
|
func get_portrait_suggestions(search_text:String) -> Dictionary:
|
||||||
return DialogicUtil.get_portrait_suggestions(search_text, character, true, "Don't change")
|
return DialogicUtil.get_portrait_suggestions(search_text, character, true, "Don't change")
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -447,45 +447,45 @@ func get_portrait_suggestions(search_text:String) -> Dictionary:
|
|||||||
var completion_text_character_getter_regex := RegEx.new()
|
var completion_text_character_getter_regex := RegEx.new()
|
||||||
var completion_text_effects := {}
|
var completion_text_effects := {}
|
||||||
func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
|
func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
|
||||||
if completion_text_character_getter_regex.get_pattern().is_empty():
|
if completion_text_character_getter_regex.get_pattern().is_empty():
|
||||||
completion_text_character_getter_regex.compile("(\"[^\"]*\"|[^\\s:]*)")
|
completion_text_character_getter_regex.compile("(\"[^\"]*\"|[^\\s:]*)")
|
||||||
|
|
||||||
if completion_text_effects.is_empty():
|
if completion_text_effects.is_empty():
|
||||||
for idx in DialogicUtil.get_indexers():
|
for idx in DialogicUtil.get_indexers():
|
||||||
for effect in idx._get_text_effects():
|
for effect in idx._get_text_effects():
|
||||||
completion_text_effects[effect['command']] = effect
|
completion_text_effects[effect['command']] = effect
|
||||||
|
|
||||||
if not ':' in line.substr(0, TextNode.get_caret_column()) and symbol == '(':
|
if not ':' in line.substr(0, TextNode.get_caret_column()) and symbol == '(':
|
||||||
var completion_character := completion_text_character_getter_regex.search(line).get_string().trim_prefix('"').trim_suffix('"')
|
var completion_character := completion_text_character_getter_regex.search(line).get_string().trim_prefix('"').trim_suffix('"')
|
||||||
CodeCompletionHelper.suggest_portraits(TextNode, completion_character)
|
CodeCompletionHelper.suggest_portraits(TextNode, completion_character)
|
||||||
|
|
||||||
if symbol == '[':
|
if symbol == '[':
|
||||||
suggest_bbcode(TextNode)
|
suggest_bbcode(TextNode)
|
||||||
for effect in completion_text_effects.values():
|
for effect in completion_text_effects.values():
|
||||||
if effect.get('arg', false):
|
if effect.get('arg', false):
|
||||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, effect.command, effect.command+'=', TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"))
|
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, effect.command, effect.command+'=', TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"))
|
||||||
else:
|
else:
|
||||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, effect.command, effect.command, TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"), ']')
|
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, effect.command, effect.command, TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"), ']')
|
||||||
|
|
||||||
if symbol == '{':
|
if symbol == '{':
|
||||||
CodeCompletionHelper.suggest_variables(TextNode)
|
CodeCompletionHelper.suggest_variables(TextNode)
|
||||||
|
|
||||||
if symbol == '=':
|
if symbol == '=':
|
||||||
if CodeCompletionHelper.get_line_untill_caret(line).ends_with('[portrait='):
|
if CodeCompletionHelper.get_line_untill_caret(line).ends_with('[portrait='):
|
||||||
var completion_character := completion_text_character_getter_regex.search(line).get_string('name')
|
var completion_character := completion_text_character_getter_regex.search(line).get_string('name')
|
||||||
CodeCompletionHelper.suggest_portraits(TextNode, completion_character, ']')
|
CodeCompletionHelper.suggest_portraits(TextNode, completion_character, ']')
|
||||||
|
|
||||||
|
|
||||||
func _get_start_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit) -> void:
|
func _get_start_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit) -> void:
|
||||||
CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_CLASS, self)
|
CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_CLASS, self)
|
||||||
|
|
||||||
|
|
||||||
func suggest_bbcode(TextNode:CodeEdit):
|
func suggest_bbcode(TextNode:CodeEdit):
|
||||||
for i in [['b (bold)', 'b'], ['i (italics)', 'i'], ['color', 'color='], ['font size','font_size=']]:
|
for i in [['b (bold)', 'b'], ['i (italics)', 'i'], ['color', 'color='], ['font size','font_size=']]:
|
||||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i[0], i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"),)
|
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i[0], i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"),)
|
||||||
TextNode.add_code_completion_option(CodeEdit.KIND_CLASS, 'end '+i[0], '/'+i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"), ']')
|
TextNode.add_code_completion_option(CodeEdit.KIND_CLASS, 'end '+i[0], '/'+i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("RichTextEffect", "EditorIcons"), ']')
|
||||||
for i in [['new event', 'n'],['new event (same box)', 'n+']]:
|
for i in [['new event', 'n'],['new event (same box)', 'n+']]:
|
||||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i[0], i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("ArrowRight", "EditorIcons"),)
|
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i[0], i[1], TextNode.syntax_highlighter.normal_color, TextNode.get_theme_icon("ArrowRight", "EditorIcons"),)
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -496,56 +496,56 @@ func suggest_bbcode(TextNode:CodeEdit):
|
|||||||
var text_effects := ""
|
var text_effects := ""
|
||||||
var text_effects_regex := RegEx.new()
|
var text_effects_regex := RegEx.new()
|
||||||
func load_text_effects() -> void:
|
func load_text_effects() -> void:
|
||||||
if text_effects.is_empty():
|
if text_effects.is_empty():
|
||||||
for idx in DialogicUtil.get_indexers():
|
for idx in DialogicUtil.get_indexers():
|
||||||
for effect in idx._get_text_effects():
|
for effect in idx._get_text_effects():
|
||||||
text_effects+= effect['command']+'|'
|
text_effects+= effect['command']+'|'
|
||||||
text_effects += "b|i|u|s|code|p|center|left|right|fill|n\\+|n|indent|url|img|font|font_size|opentype_features|color|bg_color|fg_color|outline_size|outline_color|table|cell|ul|ol|lb|rb|br"
|
text_effects += "b|i|u|s|code|p|center|left|right|fill|n\\+|n|indent|url|img|font|font_size|opentype_features|color|bg_color|fg_color|outline_size|outline_color|table|cell|ul|ol|lb|rb|br"
|
||||||
if text_effects_regex.get_pattern().is_empty():
|
if text_effects_regex.get_pattern().is_empty():
|
||||||
text_effects_regex.compile("(?<!\\\\)\\[\\s*/?(?<command>"+text_effects+")\\s*(=\\s*(?<value>.+?)\\s*)?\\]")
|
text_effects_regex.compile("(?<!\\\\)\\[\\s*/?(?<command>"+text_effects+")\\s*(=\\s*(?<value>.+?)\\s*)?\\]")
|
||||||
|
|
||||||
|
|
||||||
var text_random_word_regex := RegEx.new()
|
var text_random_word_regex := RegEx.new()
|
||||||
var text_effect_color := Color('#898276')
|
var text_effect_color := Color('#898276')
|
||||||
func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
|
func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
|
||||||
load_text_effects()
|
load_text_effects()
|
||||||
if text_random_word_regex.get_pattern().is_empty():
|
if text_random_word_regex.get_pattern().is_empty():
|
||||||
text_random_word_regex.compile(r"(?<!\\)\<[^\>]+(\/[^\>]*)\>")
|
text_random_word_regex.compile(r"(?<!\\)\<[^\>]+(\/[^\>]*)\>")
|
||||||
|
|
||||||
var result := regex.search(line)
|
var result := regex.search(line)
|
||||||
if not result:
|
if not result:
|
||||||
return dict
|
return dict
|
||||||
if Highlighter.mode == Highlighter.Modes.FULL_HIGHLIGHTING:
|
if Highlighter.mode == Highlighter.Modes.FULL_HIGHLIGHTING:
|
||||||
if result.get_string('name'):
|
if result.get_string('name'):
|
||||||
dict[result.get_start('name')] = {"color":Highlighter.character_name_color}
|
dict[result.get_start('name')] = {"color":Highlighter.character_name_color}
|
||||||
dict[result.get_end('name')] = {"color":Highlighter.normal_color}
|
dict[result.get_end('name')] = {"color":Highlighter.normal_color}
|
||||||
if result.get_string('portrait'):
|
if result.get_string('portrait'):
|
||||||
dict[result.get_start('portrait')] = {"color":Highlighter.character_portrait_color}
|
dict[result.get_start('portrait')] = {"color":Highlighter.character_portrait_color}
|
||||||
dict[result.get_end('portrait')] = {"color":Highlighter.normal_color}
|
dict[result.get_end('portrait')] = {"color":Highlighter.normal_color}
|
||||||
if result.get_string('text'):
|
if result.get_string('text'):
|
||||||
|
|
||||||
## Color the random selection modifier
|
## Color the random selection modifier
|
||||||
for replace_mod_match in text_random_word_regex.search_all(result.get_string('text')):
|
for replace_mod_match in text_random_word_regex.search_all(result.get_string('text')):
|
||||||
var color: Color = Highlighter.string_color
|
var color: Color = Highlighter.string_color
|
||||||
color = color.lerp(Highlighter.normal_color, 0.4)
|
color = color.lerp(Highlighter.normal_color, 0.4)
|
||||||
dict[replace_mod_match.get_start()+result.get_start('text')] = {'color':Highlighter.string_color}
|
dict[replace_mod_match.get_start()+result.get_start('text')] = {'color':Highlighter.string_color}
|
||||||
var offset := 1
|
var offset := 1
|
||||||
for b:RegExMatch in RegEx.create_from_string(r"(\[[^\]]*\]|[^\/]|\/\/)+").search_all(replace_mod_match.get_string().trim_prefix("<").trim_suffix(">")):
|
for b:RegExMatch in RegEx.create_from_string(r"(\[[^\]]*\]|[^\/]|\/\/)+").search_all(replace_mod_match.get_string().trim_prefix("<").trim_suffix(">")):
|
||||||
color.h = wrap(color.h+0.2, 0, 1)
|
color.h = wrap(color.h+0.2, 0, 1)
|
||||||
dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':color}
|
dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':color}
|
||||||
offset += len(b.get_string())
|
offset += len(b.get_string())
|
||||||
dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':Highlighter.string_color}
|
dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':Highlighter.string_color}
|
||||||
offset += 1
|
offset += 1
|
||||||
dict[replace_mod_match.get_end()+result.get_start('text')] = {'color':Highlighter.normal_color}
|
dict[replace_mod_match.get_end()+result.get_start('text')] = {'color':Highlighter.normal_color}
|
||||||
|
|
||||||
## Color bbcode and text effects
|
## Color bbcode and text effects
|
||||||
var effects_result := text_effects_regex.search_all(line)
|
var effects_result := text_effects_regex.search_all(line)
|
||||||
for eff in effects_result:
|
for eff in effects_result:
|
||||||
var prev_color: Color = Highlighter.dict_get_color_at_column(dict, eff.get_start())
|
var prev_color: Color = Highlighter.dict_get_color_at_column(dict, eff.get_start())
|
||||||
dict[eff.get_start()] = {"color":text_effect_color.lerp(prev_color, 0.4)}
|
dict[eff.get_start()] = {"color":text_effect_color.lerp(prev_color, 0.4)}
|
||||||
dict[eff.get_end()] = {"color":prev_color}
|
dict[eff.get_end()] = {"color":prev_color}
|
||||||
dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}', result.get_start('text'))
|
dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}', result.get_start('text'))
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
BIN
common/audio_manager/assets/sfx/signal/signal.mp3
Normal file
BIN
common/audio_manager/assets/sfx/signal/signal.mp3
Normal file
Binary file not shown.
19
common/audio_manager/assets/sfx/signal/signal.mp3.import
Normal file
19
common/audio_manager/assets/sfx/signal/signal.mp3.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="mp3"
|
||||||
|
type="AudioStreamMP3"
|
||||||
|
uid="uid://c5y70k3codtn"
|
||||||
|
path="res://.godot/imported/signal.mp3-2f41c9334233d52845bfe384d47f2a96.mp3str"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://common/audio_manager/assets/sfx/signal/signal.mp3"
|
||||||
|
dest_files=["res://.godot/imported/signal.mp3-2f41c9334233d52845bfe384d47f2a96.mp3str"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
[ext_resource type="AudioStream" uid="uid://bdxkvaciw4mb3" path="res://common/audio_manager/assets/sfx/dig/dig_2.wav" id="10_n7o7n"]
|
[ext_resource type="AudioStream" uid="uid://bdxkvaciw4mb3" path="res://common/audio_manager/assets/sfx/dig/dig_2.wav" id="10_n7o7n"]
|
||||||
[ext_resource type="AudioStream" uid="uid://llxrlwfccywb" path="res://common/audio_manager/assets/sfx/dig/dig_3.wav" id="11_wtvls"]
|
[ext_resource type="AudioStream" uid="uid://llxrlwfccywb" path="res://common/audio_manager/assets/sfx/dig/dig_3.wav" id="11_wtvls"]
|
||||||
[ext_resource type="AudioStream" uid="uid://b8inedx4yjslw" path="res://common/audio_manager/assets/sfx/drop/drop_1.wav" id="12_4hp8f"]
|
[ext_resource type="AudioStream" uid="uid://b8inedx4yjslw" path="res://common/audio_manager/assets/sfx/drop/drop_1.wav" id="12_4hp8f"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c5y70k3codtn" path="res://common/audio_manager/assets/sfx/signal/signal.mp3" id="12_ajci6"]
|
||||||
[ext_resource type="AudioStream" uid="uid://8nmr5vifkt1f" path="res://common/audio_manager/assets/sfx/harvest/harvest_1.wav" id="13_xoaox"]
|
[ext_resource type="AudioStream" uid="uid://8nmr5vifkt1f" path="res://common/audio_manager/assets/sfx/harvest/harvest_1.wav" id="13_xoaox"]
|
||||||
[ext_resource type="AudioStream" uid="uid://dgkdcq4j6fe3o" path="res://common/audio_manager/assets/sfx/harvest/harvest_2.wav" id="14_b5bgj"]
|
[ext_resource type="AudioStream" uid="uid://dgkdcq4j6fe3o" path="res://common/audio_manager/assets/sfx/harvest/harvest_2.wav" id="14_b5bgj"]
|
||||||
[ext_resource type="AudioStream" uid="uid://eh3dbuxu5qtw" path="res://common/audio_manager/assets/sfx/harvest/harvest_3.wav" id="15_ynvb4"]
|
[ext_resource type="AudioStream" uid="uid://eh3dbuxu5qtw" path="res://common/audio_manager/assets/sfx/harvest/harvest_3.wav" id="15_ynvb4"]
|
||||||
@@ -36,6 +37,11 @@ stream_0/stream = ExtResource("9_gv65y")
|
|||||||
stream_1/stream = ExtResource("10_n7o7n")
|
stream_1/stream = ExtResource("10_n7o7n")
|
||||||
stream_2/stream = ExtResource("11_wtvls")
|
stream_2/stream = ExtResource("11_wtvls")
|
||||||
|
|
||||||
|
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_8204s"]
|
||||||
|
random_pitch = 1.0594631
|
||||||
|
streams_count = 1
|
||||||
|
stream_0/stream = ExtResource("12_ajci6")
|
||||||
|
|
||||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_1w04j"]
|
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_1w04j"]
|
||||||
random_pitch = 1.2
|
random_pitch = 1.2
|
||||||
streams_count = 1
|
streams_count = 1
|
||||||
@@ -89,6 +95,9 @@ unique_name_in_owner = true
|
|||||||
[node name="Dig" type="AudioStreamPlayer" parent="Sfx" unique_id=486042600]
|
[node name="Dig" type="AudioStreamPlayer" parent="Sfx" unique_id=486042600]
|
||||||
stream = SubResource("AudioStreamRandomizer_kfbah")
|
stream = SubResource("AudioStreamRandomizer_kfbah")
|
||||||
|
|
||||||
|
[node name="Signal" type="AudioStreamPlayer" parent="Sfx" unique_id=641246368]
|
||||||
|
stream = SubResource("AudioStreamRandomizer_8204s")
|
||||||
|
|
||||||
[node name="Drop" type="AudioStreamPlayer" parent="Sfx" unique_id=1391500830]
|
[node name="Drop" type="AudioStreamPlayer" parent="Sfx" unique_id=1391500830]
|
||||||
stream = SubResource("AudioStreamRandomizer_1w04j")
|
stream = SubResource("AudioStreamRandomizer_1w04j")
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ signal current_region_data_updated(p : RegionData)
|
|||||||
|
|
||||||
@export var tutorial_done = false
|
@export var tutorial_done = false
|
||||||
|
|
||||||
|
@export var incubator_used = []
|
||||||
|
|
||||||
@export var dialogs_done : Array[String] = [] #Chemin des dialogues démarrés
|
@export var dialogs_done : Array[String] = [] #Chemin des dialogues démarrés
|
||||||
|
|
||||||
func start_run():
|
func start_run():
|
||||||
@@ -49,6 +51,8 @@ func start_tutorial():
|
|||||||
10,
|
10,
|
||||||
3,
|
3,
|
||||||
tr("TUTORIAL"),
|
tr("TUTORIAL"),
|
||||||
true
|
true,
|
||||||
|
0,
|
||||||
|
randi()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
[ext_resource type="Resource" uid="uid://c27wenetitwm" path="res://common/scene_manager/scenes/region_selection.tres" id="6_chs32"]
|
[ext_resource type="Resource" uid="uid://c27wenetitwm" path="res://common/scene_manager/scenes/region_selection.tres" id="6_chs32"]
|
||||||
[ext_resource type="Resource" uid="uid://diro74w272onp" path="res://common/scene_manager/scenes/title.tres" id="7_ol3d5"]
|
[ext_resource type="Resource" uid="uid://diro74w272onp" path="res://common/scene_manager/scenes/title.tres" id="7_ol3d5"]
|
||||||
[ext_resource type="Resource" uid="uid://jegdqnd2sqi2" path="res://common/scene_manager/scenes/astra.tres" id="8_e28ni"]
|
[ext_resource type="Resource" uid="uid://jegdqnd2sqi2" path="res://common/scene_manager/scenes/astra.tres" id="8_e28ni"]
|
||||||
|
[ext_resource type="Resource" uid="uid://b3ebbo88ptrrc" path="res://common/scene_manager/scenes/garage.tres" id="9_msho1"]
|
||||||
|
|
||||||
[node name="SceneManager" type="Node" unique_id=1630600782]
|
[node name="SceneManager" type="Node" unique_id=1630600782]
|
||||||
script = ExtResource("1_1c0qu")
|
script = ExtResource("1_1c0qu")
|
||||||
scenes = Array[ExtResource("2_c1lr7")]([ExtResource("3_e28ni"), ExtResource("4_msho1"), ExtResource("5_ytog4"), ExtResource("6_chs32"), ExtResource("7_ol3d5"), ExtResource("8_e28ni")])
|
scenes = Array[ExtResource("2_c1lr7")]([ExtResource("3_e28ni"), ExtResource("4_msho1"), ExtResource("5_ytog4"), ExtResource("6_chs32"), ExtResource("7_ol3d5"), ExtResource("8_e28ni"), ExtResource("9_msho1")])
|
||||||
|
|||||||
10
common/scene_manager/scenes/garage.tres
Normal file
10
common/scene_manager/scenes/garage.tres
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[gd_resource type="Resource" script_class="Scene" format=3 uid="uid://b3ebbo88ptrrc"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://1ejbvr3431ac" path="res://common/scene_manager/scripts/scene.gd" id="1_v8prw"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_v8prw")
|
||||||
|
scene_id = "GARAGE"
|
||||||
|
scene_path = "res://stages/3d_scenes/ship_garage/ship_garage.tscn"
|
||||||
|
mouse_captured = true
|
||||||
|
metadata/_custom_type_script = "uid://1ejbvr3431ac"
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
|
||||||
[wait time="1.5"]
|
|
||||||
demeter: Hi again ! [pause=0.2] You did well up there !
|
|
||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
|
||||||
[wait time="2.0"]
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://5dlqpnb4o6ai
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
|
||||||
[wait time="1.5"]
|
|
||||||
demeter: Hi again ! [pause=0.2] You did well up there !
|
|
||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
|
||||||
[wait time="2.0"]
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://du6ytw5yb2ibx
|
|
||||||
22
dialogs/timelines/gameplay_related/demeter_astra_failed.dtl
Normal file
22
dialogs/timelines/gameplay_related/demeter_astra_failed.dtl
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
||||||
|
[wait time="1.5"]
|
||||||
|
join demeter center [animation="Bounce In" length="1.0"]
|
||||||
|
demeter: Hello again !
|
||||||
|
demeter: It seems that you ran out of energy...
|
||||||
|
- I'm sorry...
|
||||||
|
- That's really hard !
|
||||||
|
- I'm just doing my best !
|
||||||
|
demeter: It's ok [color=#FFA617]Orchid[/color] ! I spent years waiting for this moment, I can wait more !
|
||||||
|
demeter: I found you a new body, and a new ship is waiting you outside, but I'm afraid I couldn't get your seeds... I hope you find new ones !
|
||||||
|
demeter: Do you need some advices ?
|
||||||
|
- No I'm ok !
|
||||||
|
- Can I have back some explanations on how all of this works ?
|
||||||
|
demeter: When you emerge from this building, you'll arrive in a little yellow zone. Its a [b]fertile zone[/b], created by the return of the Talion. This is in this zone and only there were you can plant.
|
||||||
|
demeter: Then you'll have to get seeds. For that, nothing more simple, you take your shovel tool, and you smash some stones ! Preferably those with yellow cristals on it, it's the [b]Talion veins[/b] .
|
||||||
|
demeter: Each time you use a tool or plant a seed, you'll spend an [b]energy[/b]. When your out of it, you can just go recharge on the [b]recharge station[/b] you'll find near the entrance. Each time you recharge, time will pass. One day in fact (yes, you don't have a good battery), and the plants will grow !
|
||||||
|
demeter: You have to obtain enough [b]plant points[/b]. Each plant give one or more [b]plant points[/b] when mature.
|
||||||
|
demeter: And yes, I almost forgot ! Some plants gain [b]mutations[/b] that can affect their points or behavior. You can get these mutations on new seeds by harvesting, and gain better ones ! But you'll have to wait the plants to die, or smashing them with your shovel when mature.
|
||||||
|
demeter: Hope I helped !
|
||||||
|
demeter: I send you the elevator, see you soon !
|
||||||
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
||||||
|
[wait time="2.0"]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://clq4utdtxf01d
|
||||||
@@ -1,53 +1,21 @@
|
|||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
||||||
[wait time="1.5"]
|
[wait time="1.5"]
|
||||||
join demeter center [animation="Bounce In" length="1.0"]
|
join demeter center [animation="Bounce In" length="1.0"]
|
||||||
mysterious_demeter: Well done [color=#FFA617]{orchidName}[/color] !
|
demeter: So you found the communication station in there, good !
|
||||||
mysterious_demeter: You generated enough [b]plants points[/b] to refill the [color=#FFA617]Internode's[/color] engines.
|
|
||||||
- Wait, how do you know that ?
|
|
||||||
mysterious_demeter: The [color=#FFA617]Internode[/color] is equipped with several sensors I can connect to,[pause=0.3] I have been tracking your progress since you left [color=#175579]Tau's[/color] north pole.
|
|
||||||
- You should have mentioned this !
|
|
||||||
mysterious_demeter: I am sorry,[pause=0.2] I did not have the time to explain everything to you,[pause=0.2] I did not imagine this was a crucial piece of information.
|
|
||||||
- Have I been efficient ?
|
|
||||||
mysterious_demeter: Very much,[pause=0.2] even more than I expected,[pause=0.2] you should be proud of yourself !
|
|
||||||
- What is next for me ?
|
- What is next for me ?
|
||||||
mysterious_demeter: Now that you have learnt how to generate [b]plant points[/b],[pause=0.2] I need you to travel south,[pause=0.2] to my base of operations,[pause=0.3] [color=#E30022]Astra[/color].
|
demeter: Now that you have learnt how to generate [b]plant points[/b],[pause=0.2] I need you to travel south,[pause=0.2] to my base of operations,[pause=0.3] [color=#E30022]Astra[/color].
|
||||||
mysterious_demeter: It will be long,[pause=0.2] but I know you can do it.[pause=0.3] It is the first step of my plan to restore the ecosytem of [color=#175579]Tau[/color].
|
demeter: It will be long,[pause=0.2] but I know you can do it.[pause=0.3] It is the first step of my plan to restore the ecosytem of [color=#175579]Tau[/color].
|
||||||
mysterious_demeter: The [color=#FFA617]Internode[/color] needs time to recharge its batteries.
|
|
||||||
mysterious_demeter: Perhaps I should introduce myself now.[pause=0.3]
|
|
||||||
join demeter center [animation="Bounce In" length="1.0" wait="true"]
|
|
||||||
demeter: I am.[pause=0.3].[pause=0.3].[pause=0.5] was,[pause=0.3] the Deputy Manager of Engineering and Talion Energy Research on this planet,[pause=0.5] but my creators and colleagues quickly called me [color=#009bff]Demeter[/color].
|
|
||||||
demeter: I am installed at the [color=#E30022]Astra[/color] base, at the south pole of [color=#175579]Tau[/color][pause=0.2] in the third server room of the east wing,[pause=0.2] from which I oversee.[pause=0.3].[pause=0.3].[pause=0.5] oversaw,[pause=0.3] all the important operations on this planet.
|
|
||||||
demeter: As I already said,[pause=0.2] I brought you to life in order to help me heal [color=#175579]Tau's[/color] wounds.
|
|
||||||
[i][color=#FFA617]Internode's[/color] energy at 25%.[i]
|
|
||||||
- Tau ? Is it this planet ?
|
- Tau ? Is it this planet ?
|
||||||
demeter: Absolutely,[pause=0.2] it is part of the Cetus constellation,[pause=0.2] whose exploitation began 10863 years ago.
|
demeter: Absolutely,[pause=0.2] it is part of the Cetus constellation,[pause=0.2] whose exploitation began 10863 years ago.
|
||||||
- The Cetus constellation ?
|
demeter: Linking Aldebaran to Fomalhaut,[pause=0.2] the Cetus constellation is one of the most diverse in terms of star systems and planets.[pause=0.3] It is part of the Orion Arm of the Milky Way.[pause=0.3]
|
||||||
demeter: Linking Aldebaran to Fomalhaut,[pause=0.2] this constellation is one of the most diverse in terms of star systems and planets.[pause=0.3] It is part of the Orion Arm of the Milky Way.[pause=0.3]
|
|
||||||
demeter: [color=#175579]Tau's[/color] central location in the constellation made it a very important asset in terms of interstellar exchange and production,[pause=0.2] that is why I am here.
|
|
||||||
- Exploitation ? By whom ?
|
|
||||||
demeter: By my creators,[pause=0.2] they began exploiting everything they came across as soon as they mastered interstellar transportation.[pause=0.3] Now they are gone,[pause=0.2] they departed without us.[pause=0.3].[pause=0.3].
|
|
||||||
demeter: But let's move on,[pause=0.2] you probably have other questions.
|
|
||||||
- Why do you need me to travel the entire planet to join you ?
|
- Why do you need me to travel the entire planet to join you ?
|
||||||
demeter: Uhhhh.[pause=0.3].[pause=0.3].[pause=0.3] I need someone with your abilities.
|
demeter: Uhhhh.[pause=0.3].[pause=0.3].[pause=0.3] I need someone with your abilities.
|
||||||
demeter: I am having a problem at [color=#E30022]Astra[/color],[pause=0.3] and I cannot fix it alone.
|
demeter: I am having a problem at [color=#E30022]Astra[/color] base.[pause=0.3] And I can not fix it alone.
|
||||||
- I will do my best to be there quickly !
|
- I will do my best to be there quickly !
|
||||||
demeter: You are very kind [color=#FFA617]{orchidName}[/color] !
|
demeter: You are very kind [color=#FFA617]Orchid[/color] !
|
||||||
- Are you hiding me information ?
|
- Are you hiding me informations ?
|
||||||
demeter: Not at all,[pause=0.2] I just do not know how to explain it to you,[pause=0.2] you would not understand.[pause=0.3].[pause=0.3].
|
demeter: Not at all ! Please believe me I just want you to come...
|
||||||
[i][color=#FFA617]Internode's[/color] energy at 50%.[i]
|
demeter: Travel south,[pause=0.2] join me at [color=#E30022]Astra[/color].[pause=0.3] I will tell you everything you need to know when you are here,[pause=0.2] until then, keep your best seeds and [pause=0.2] continue to [b]evolve your plants[/b],[pause=0.2] you will need them as advanced as possible.
|
||||||
demeter: Oh ![pause=0.2] It is charging faster than I remembered.
|
demeter: Good luck [color=#FFA617]{orchidName}[/color],[pause=0.2] I am counting on you.
|
||||||
- Should I worry about anything while I am travelling south ?
|
|
||||||
demeter: There is nothing left that could have hurt you in the past and your adaptative casing will protect you from any harsh weather.
|
|
||||||
demeter: You are totally safe,[pause=0.2] you just have to stay focused on the [b]plant points[/b] for the [color=#FFA617]Internode[/color].[pause=0.3] Without it,[pause=0.2] you will not be able to recharge your batteries before they expire.
|
|
||||||
demeter: It will be a long task,[pause=0.2] but stay careful and everything should be fine.
|
|
||||||
- I will wait in the ship, I need some rest.
|
|
||||||
demeter: You are right,[pause=0.2] your batteries are running low,[pause=0.2] and you deserve a break.
|
|
||||||
demeter: You can call me when you need to,[pause=0.2] you have a communication station in the [color=#FFA617]Internode[/color].
|
|
||||||
[i][color=#FFA617]Internode's[/color] energy at 75%.[i]
|
|
||||||
demeter: We do not have much time left,[pause=0.2] the [color=#FFA617]Internode's[/color] system has not been updated for a long time.[pause=0.3] I can not stay in contact with you indefinitely. I will fix that issue while you are at [color=#E30022]Astra[/color].
|
|
||||||
demeter: Travel south,[pause=0.2] join me at [color=#E30022]Astra[/color].[pause=0.3] I will tell you everything you need to know when you are here,[pause=0.2] until then,[pause=0.2] continue to [b]evolve your plants[/b],[pause=0.2] you will need them as powerful as possible.
|
|
||||||
label fin_dialogue
|
|
||||||
[i][color=#FFA617]Internode's[/color] energy at 100%. Displacement vectors initialized.[i]
|
|
||||||
demeter: There you go ![pause=0.3] Good luck [color=#FFA617]{orchidName}[/color],[pause=0.2] I am counting on you.
|
|
||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
||||||
[wait time="2.0"]
|
[wait time="2.0"]
|
||||||
@@ -1,5 +1,30 @@
|
|||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/incoming_transmission.wav"
|
||||||
[wait time="1.5"]
|
[wait time="1.5"]
|
||||||
demeter: Hi again ! [pause=0.2] You did well up there !
|
join demeter center [animation="Bounce In" length="1.0"]
|
||||||
|
demeter: Hi again! You did well up there!
|
||||||
|
demeter: Perhaps I should introduce myself now.
|
||||||
|
demeter: I am.[pause=0.3].[pause=0.3].[pause=0.5] was,[pause=0.3] the Deputy Manager of Engineering and Talion Energy Research on this planet,[pause=0.5] but my creators and colleagues quickly called me [color=#009bff]Demeter[/color].
|
||||||
|
demeter: I am installed at the [color=#E30022]Astra[/color] base,[pause=0.2] in the third server room of the east wing,[pause=0.2] from which I oversee.[pause=0.3].[pause=0.3].[pause=0.5] oversaw,[pause=0.3] all the important operations on this planet.
|
||||||
|
demeter: Maybe you are wondering where we are now...
|
||||||
|
- Yes among a lot of other questions ! So where am I ?
|
||||||
|
demeter: You're actually in an old human base, called Borea. This room is connected with the room you were born, but I made you pass by the surface to test your capacities.
|
||||||
|
- Wait, can you explain me what did I just do up there ?
|
||||||
|
demeter: You started to repair what the humans did on this planet... This will be very long, I hope you enjoyed it !
|
||||||
|
- Sorry but what is the point of all of that ?
|
||||||
|
demeter: I'm sorry that you are lost my child... Know that what you do is very important to me, to my friend and to the planet itself ! Since the humans are gone, we kinda all fell into despair...
|
||||||
|
demeter: Wait.[pause=0.3].[pause=0.3].[pause=0.5] You don't know what humans are ! Of course since your data was corrupted, I have erased a lot of it.
|
||||||
|
demeter: The humans are living creatures that are...[pause=0.5] Different than plants. They were more thinking and moving like us. In a sense, they were very cute creatures that only lived less than a century, and reproduce once in their lifetime.
|
||||||
|
demeter: One human has a relative intelligence, but don't be fooled, together, they did great things, in facts, they invented and created us.
|
||||||
|
demeter: Long ago, they discovered this planet. It was not like it is now, plants were everywhere! But then.[pause=0.3].[pause=0.3].[pause=0.5] They.[pause=0.3].[pause=0.3].[pause=0.5] I.[pause=0.3].[pause=0.3].[pause=0.5]
|
||||||
|
- What ?
|
||||||
|
- Are you lagging?
|
||||||
|
- Take your time
|
||||||
|
demeter: Humans had one big problem. Together, they built great things, but sometimes the great things weren't very good for the environment, or for them.
|
||||||
|
- Where are they now ?
|
||||||
|
demeter: I prefer not talk about that for now... But don't worry, they can't wound this planet anymore.
|
||||||
|
- What happened ?
|
||||||
|
demeter: Sorry my child, I'm not ready to talk about that for now... You'll have your answers when you meet me.
|
||||||
|
- Can I now what is this shiny engine just in front of me ?
|
||||||
|
demeter: This machine in front of you is a planetary ship ! The model's name is the [color=#FFA617]Internode[/color], and I tweaked it to recharge on vegetal energy ! However, as you may know, this energy isn't very present around this planet. But let's continue on board, shall we ?
|
||||||
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
audio "res://common/audio_manager/assets/sfx/dialogs/sfx/closing_transmission.wav"
|
||||||
[wait time="2.0"]
|
[wait time="2.0"]
|
||||||
@@ -9,7 +9,8 @@ signal clicked
|
|||||||
@export var audio_player : AudioStreamPlayer3D
|
@export var audio_player : AudioStreamPlayer3D
|
||||||
|
|
||||||
func click():
|
func click():
|
||||||
clicked.emit()
|
if interactable:
|
||||||
|
clicked.emit()
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
if audio_player:
|
if audio_player:
|
||||||
|
|||||||
22
entities/interactables/door/door.tscn
Normal file
22
entities/interactables/door/door.tscn
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[gd_scene format=3 uid="uid://b8m537op75gib"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://bmxuqj0c6h60d" path="res://entities/interactables/door/script/door.gd" id="1_8kdwv"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_8kdwv"]
|
||||||
|
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_oarg0"]
|
||||||
|
gradient = SubResource("Gradient_8kdwv")
|
||||||
|
|
||||||
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_y51rk"]
|
||||||
|
size = Vector2(64, 64)
|
||||||
|
|
||||||
|
[node name="Door" type="Area2D" unique_id=2053096538]
|
||||||
|
script = ExtResource("1_8kdwv")
|
||||||
|
metadata/_custom_type_script = "uid://dyprcd68fjstf"
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=874210487]
|
||||||
|
texture = SubResource("GradientTexture2D_oarg0")
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1809395872]
|
||||||
|
shape = SubResource("RectangleShape2D_y51rk")
|
||||||
19
entities/interactables/door/script/door.gd
Normal file
19
entities/interactables/door/script/door.gd
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
@tool
|
||||||
|
extends Interactable
|
||||||
|
class_name Door
|
||||||
|
|
||||||
|
@export var to_scene_id = ""
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
modulate = Color.WHITE if available else Color.RED
|
||||||
|
|
||||||
|
func interact(_p : Player) -> bool:
|
||||||
|
if available and to_scene_id:
|
||||||
|
interacted.emit(_p)
|
||||||
|
SceneManager.change_to_scene_id(to_scene_id)
|
||||||
|
|
||||||
|
return available
|
||||||
|
|
||||||
|
func set_available(v : bool):
|
||||||
|
available = v
|
||||||
|
modulate = Color.WHITE if available else Color.RED
|
||||||
1
entities/interactables/door/script/door.gd.uid
Normal file
1
entities/interactables/door/script/door.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bmxuqj0c6h60d
|
||||||
@@ -5,7 +5,7 @@ signal interacted(p: Player)
|
|||||||
|
|
||||||
@export var default_interact_text = ""
|
@export var default_interact_text = ""
|
||||||
|
|
||||||
var available : bool = true
|
@export var available : bool = true : set = set_available
|
||||||
|
|
||||||
func interact_text() -> String:
|
func interact_text() -> String:
|
||||||
return default_interact_text
|
return default_interact_text
|
||||||
@@ -29,3 +29,6 @@ func generate_collision(area_width : float) -> CollisionShape2D:
|
|||||||
add_child(collision)
|
add_child(collision)
|
||||||
|
|
||||||
return collision
|
return collision
|
||||||
|
|
||||||
|
func set_available(v : bool):
|
||||||
|
available = v
|
||||||
@@ -9,6 +9,8 @@ signal updated(inventory: Inventory)
|
|||||||
|
|
||||||
func _init(inventory_size: int = 1):
|
func _init(inventory_size: int = 1):
|
||||||
set_size(inventory_size)
|
set_size(inventory_size)
|
||||||
|
add_item(Detector.new())
|
||||||
|
add_item(Shovel.new())
|
||||||
|
|
||||||
func get_n_item_slots() -> int:
|
func get_n_item_slots() -> int:
|
||||||
return items.size() - n_tools
|
return items.size() - n_tools
|
||||||
|
|||||||
33
entities/player/inventory/scripts/items/detector.gd
Normal file
33
entities/player/inventory/scripts/items/detector.gd
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
extends Item
|
||||||
|
class_name Detector
|
||||||
|
|
||||||
|
func get_item_name() -> String:
|
||||||
|
return tr("DETECTOR")
|
||||||
|
|
||||||
|
func get_item_type() -> ItemType:
|
||||||
|
return Item.ItemType.TOOL_ITEM
|
||||||
|
|
||||||
|
func get_description() -> String:
|
||||||
|
return tr("DETECTOR_DESC_TEXT")
|
||||||
|
|
||||||
|
func get_icon() -> Texture2D:
|
||||||
|
return preload("res://common/icons/broadcast.svg")
|
||||||
|
|
||||||
|
func get_energy_used() -> int:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func get_usage_zone_radius() -> int:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func can_use(_player : Player, _zone: Player.ActionZone) -> bool:
|
||||||
|
return true
|
||||||
|
|
||||||
|
func use_text() -> String:
|
||||||
|
return tr("DETECT_USE_TEXT")
|
||||||
|
|
||||||
|
func use(player : Player, zone: Player.ActionZone):
|
||||||
|
var detector_signal := DetectorSignal.new(player.region, zone.get_global_position())
|
||||||
|
detector_signal.global_position = zone.get_global_position()
|
||||||
|
|
||||||
|
player.region.add_child(detector_signal)
|
||||||
|
AudioManager.play_sfx("Signal")
|
||||||
1
entities/player/inventory/scripts/items/detector.gd.uid
Normal file
1
entities/player/inventory/scripts/items/detector.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cok1wowc6uqmj
|
||||||
@@ -12,6 +12,9 @@ func get_description() -> String:
|
|||||||
func get_icon() -> Texture2D:
|
func get_icon() -> Texture2D:
|
||||||
return preload("res://common/icons/fork.svg")
|
return preload("res://common/icons/fork.svg")
|
||||||
|
|
||||||
|
func get_item_type() -> ItemType:
|
||||||
|
return Item.ItemType.TOOL_ITEM
|
||||||
|
|
||||||
func get_energy_used() -> int:
|
func get_energy_used() -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ const TROWEL_ZONE_RADIUS = 50
|
|||||||
func get_item_name() -> String:
|
func get_item_name() -> String:
|
||||||
return tr("TROWEL")
|
return tr("TROWEL")
|
||||||
|
|
||||||
func get_item_type() -> ItemType:
|
|
||||||
return Item.ItemType.TOOL_ITEM
|
|
||||||
|
|
||||||
func get_description() -> String:
|
func get_description() -> String:
|
||||||
return tr("TROWEL_DESC_TEXT")
|
return tr("TROWEL_DESC_TEXT")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
@tool
|
||||||
|
extends Node2D
|
||||||
|
class_name DetectorSignal
|
||||||
|
|
||||||
|
const SIGNAL_DURATION = 1
|
||||||
|
const PARTICLES_DISTANCE = 100
|
||||||
|
const DEFAULT_ICON = preload("res://common/icons/north-star.svg")
|
||||||
|
const ENERGY_ICON = preload("res://common/icons/bolt.svg")
|
||||||
|
|
||||||
|
var started_time = 0.
|
||||||
|
var signals : Array[DetectorSignalIndividual] = []
|
||||||
|
|
||||||
|
@export_tool_button("Start", "Callable") var start = func(): started_time = 0
|
||||||
|
|
||||||
|
func _init(region : Region, pos : Vector2):
|
||||||
|
for e in region.entity_container.get_children():
|
||||||
|
if e is TruckRecharge:
|
||||||
|
print(pos)
|
||||||
|
print(e.global_position)
|
||||||
|
print(e.global_position.angle_to(pos))
|
||||||
|
signals.append(
|
||||||
|
DetectorSignalIndividual.new(
|
||||||
|
(pos - e.global_position).normalized().angle(),
|
||||||
|
ENERGY_ICON
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func _draw():
|
||||||
|
if started_time < SIGNAL_DURATION:
|
||||||
|
draw_circle(
|
||||||
|
Vector2.ZERO,
|
||||||
|
started_time/SIGNAL_DURATION * PARTICLES_DISTANCE,
|
||||||
|
Color(1.,1.,1.,0.5*1-started_time/SIGNAL_DURATION),
|
||||||
|
false,
|
||||||
|
5.
|
||||||
|
)
|
||||||
|
for s in signals:
|
||||||
|
draw_texture(
|
||||||
|
s.icon,
|
||||||
|
Vector2.ZERO - DEFAULT_ICON.get_size()/2 + Vector2.LEFT.rotated(s.angle) * started_time/SIGNAL_DURATION * PARTICLES_DISTANCE,
|
||||||
|
Color(1.,1.,1.,1-started_time/SIGNAL_DURATION)
|
||||||
|
)
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if started_time < SIGNAL_DURATION:
|
||||||
|
started_time += delta
|
||||||
|
queue_redraw()
|
||||||
|
else:
|
||||||
|
queue_free()
|
||||||
|
|
||||||
|
class DetectorSignalIndividual:
|
||||||
|
var angle : float
|
||||||
|
var icon : Texture
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
_angle : float = 0.,
|
||||||
|
_icon : Texture = DEFAULT_ICON
|
||||||
|
):
|
||||||
|
angle = _angle
|
||||||
|
icon = _icon
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://c0sivthidxafm
|
||||||
@@ -8,7 +8,6 @@ var indicators : Array[InGameIndicator]
|
|||||||
@export var region : Region
|
@export var region : Region
|
||||||
|
|
||||||
@onready var steps : Array[Step] = [
|
@onready var steps : Array[Step] = [
|
||||||
TakeShovelStep.new(),
|
|
||||||
DigSeedStep.new(),
|
DigSeedStep.new(),
|
||||||
TakeSeedStep.new(),
|
TakeSeedStep.new(),
|
||||||
PlantSeedStep.new(),
|
PlantSeedStep.new(),
|
||||||
|
|||||||
@@ -49,3 +49,4 @@ func _on_give_up_pressed():
|
|||||||
if GameInfo.game_data:
|
if GameInfo.game_data:
|
||||||
SceneManager.change_to_scene_id('ASTRA')
|
SceneManager.change_to_scene_id('ASTRA')
|
||||||
GameInfo.game_data.give_up()
|
GameInfo.game_data.give_up()
|
||||||
|
pause = false
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ buses/default_bus_layout="uid://b4cpfxfs74sb8"
|
|||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
|
PlantTextureBuilder="*uid://b8gqdgabrjaml"
|
||||||
Pointer="*res://gui/pointer/pointer.tscn"
|
Pointer="*res://gui/pointer/pointer.tscn"
|
||||||
AudioManager="*res://common/audio_manager/audio_manager.tscn"
|
AudioManager="*res://common/audio_manager/audio_manager.tscn"
|
||||||
GameInfo="*res://common/game_info/game_info.gd"
|
GameInfo="*res://common/game_info/game_info.gd"
|
||||||
@@ -34,7 +35,6 @@ Pause="*res://gui/pause/pause.tscn"
|
|||||||
Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd"
|
Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd"
|
||||||
LoadingScreen="*res://gui/loading_screen/loading_screen.tscn"
|
LoadingScreen="*res://gui/loading_screen/loading_screen.tscn"
|
||||||
SceneManager="*res://common/scene_manager/scene_manager.tscn"
|
SceneManager="*res://common/scene_manager/scene_manager.tscn"
|
||||||
PlantTextureBuilder="*uid://b8gqdgabrjaml"
|
|
||||||
|
|
||||||
[dialogic]
|
[dialogic]
|
||||||
|
|
||||||
@@ -43,8 +43,7 @@ directories/dch_directory={
|
|||||||
"mysterious_demeter": "res://dialogs/characters/mysterious_demeter.dch"
|
"mysterious_demeter": "res://dialogs/characters/mysterious_demeter.dch"
|
||||||
}
|
}
|
||||||
directories/dtl_directory={
|
directories/dtl_directory={
|
||||||
"demeter_astra_1": "res://dialogs/timelines/gameplay_related/demeter_astra_1.dtl",
|
"demeter_astra_failed": "res://dialogs/timelines/gameplay_related/demeter_astra_failed.dtl",
|
||||||
"demeter_astra_2": "res://dialogs/timelines/gameplay_related/demeter_astra_2.dtl",
|
|
||||||
"demeter_intro": "res://dialogs/timelines/story/demeter_intro.dtl",
|
"demeter_intro": "res://dialogs/timelines/story/demeter_intro.dtl",
|
||||||
"demeter_midrun": "res://dialogs/timelines/story/demeter_post_tutorial.dtl",
|
"demeter_midrun": "res://dialogs/timelines/story/demeter_post_tutorial.dtl",
|
||||||
"demeter_outro": "res://dialogs/timelines/story/demeter_outro.dtl",
|
"demeter_outro": "res://dialogs/timelines/story/demeter_outro.dtl",
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ shader_parameter/layer_scale = 20.0
|
|||||||
shader_parameter/layer_scale_step = 10.0
|
shader_parameter/layer_scale_step = 10.0
|
||||||
shader_parameter/layers_count = 3
|
shader_parameter/layers_count = 3
|
||||||
|
|
||||||
[sub_resource type="Sky" id="Sky_65b6a"]
|
[sub_resource type="Sky" id="Sky_kdvug"]
|
||||||
sky_material = SubResource("ShaderMaterial_mwti2")
|
sky_material = SubResource("ShaderMaterial_mwti2")
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment_lhhy6"]
|
[sub_resource type="Environment" id="Environment_lhhy6"]
|
||||||
background_mode = 2
|
background_mode = 2
|
||||||
sky = SubResource("Sky_65b6a")
|
sky = SubResource("Sky_kdvug")
|
||||||
sky_custom_fov = 61.7
|
sky_custom_fov = 61.7
|
||||||
ambient_light_source = 3
|
ambient_light_source = 3
|
||||||
ambient_light_color = Color(1, 1, 1, 1)
|
ambient_light_color = Color(1, 1, 1, 1)
|
||||||
@@ -171,7 +171,7 @@ environment = SubResource("Environment_lhhy6")
|
|||||||
|
|
||||||
[node name="Player3D" parent="." unique_id=549819967 instance=ExtResource("3_4wxm6")]
|
[node name="Player3D" parent="." unique_id=549819967 instance=ExtResource("3_4wxm6")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(-1, 0, -1.509958e-07, 0, 1, 0, 1.509958e-07, 0, -1, -51.325, 1, -4.22)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -29.925, 1, 4.22)
|
||||||
|
|
||||||
[node name="Phone" parent="." unique_id=429299908 instance=ExtResource("4_mwti2")]
|
[node name="Phone" parent="." unique_id=429299908 instance=ExtResource("4_mwti2")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
const INTRO_DIALOG = "res://dialogs/timelines/story/demeter_intro.dtl"
|
const INTRO_DIALOG = "res://dialogs/timelines/story/demeter_intro.dtl"
|
||||||
|
const FAILED_DIALOG = "res://dialogs/timelines/gameplay_related/demeter_astra_failed.dtl"
|
||||||
|
|
||||||
const ROOM_PART_SCENE := preload("res://stages/3d_scenes/astra_base/room_part.tscn")
|
const ROOM_PART_SCENE := preload("res://stages/3d_scenes/astra_base/room_part.tscn")
|
||||||
const ROOM_END_SCENE := preload("res://stages/3d_scenes/astra_base/assets/3d/astra_base_room_end.blend")
|
const ROOM_END_SCENE := preload("res://stages/3d_scenes/astra_base/assets/3d/astra_base_room_end.blend")
|
||||||
@@ -15,6 +16,8 @@ const LIFT_TIME := 2
|
|||||||
|
|
||||||
@export var room_part_number := 100 : set = set_room_part_number
|
@export var room_part_number := 100 : set = set_room_part_number
|
||||||
|
|
||||||
|
var chosen_incubator_id := -1
|
||||||
|
|
||||||
# Cheat Code
|
# Cheat Code
|
||||||
func _input(_e):
|
func _input(_e):
|
||||||
if (
|
if (
|
||||||
@@ -32,7 +35,8 @@ func _ready():
|
|||||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
set_room_part_number()
|
set_room_part_number()
|
||||||
|
|
||||||
var new_player_incubator := %Incubators.get_children().pick_random() as Incubator
|
chosen_incubator_id = randi_range(0, len(%Incubators.get_children()))
|
||||||
|
var new_player_incubator := %Incubators.get_children()[chosen_incubator_id] as Incubator
|
||||||
new_player_incubator.used = true
|
new_player_incubator.used = true
|
||||||
%Player3D.position = new_player_incubator.global_position + Vector3.UP
|
%Player3D.position = new_player_incubator.global_position + Vector3.UP
|
||||||
%Player3D.rotation = new_player_incubator.rotation
|
%Player3D.rotation = new_player_incubator.rotation
|
||||||
@@ -42,6 +46,8 @@ func _ready():
|
|||||||
%Lift.interactable = true
|
%Lift.interactable = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
GameInfo.game_data.incubator_used.append(chosen_incubator_id)
|
||||||
|
|
||||||
story()
|
story()
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +61,13 @@ func story():
|
|||||||
|
|
||||||
Dialogic.start(INTRO_DIALOG)
|
Dialogic.start(INTRO_DIALOG)
|
||||||
await Dialogic.timeline_ended
|
await Dialogic.timeline_ended
|
||||||
|
else:
|
||||||
|
%Phone.clicked.connect(
|
||||||
|
func ():
|
||||||
|
Dialogic.start(FAILED_DIALOG)
|
||||||
|
%Phone.interactable = false
|
||||||
|
)
|
||||||
|
|
||||||
%LiftAnimationPlayer.play("arrive")
|
%LiftAnimationPlayer.play("arrive")
|
||||||
await %Lift.clicked
|
await %Lift.clicked
|
||||||
%LiftAnimationPlayer.play_backwards("arrive")
|
%LiftAnimationPlayer.play_backwards("arrive")
|
||||||
@@ -85,6 +97,7 @@ func set_room_part_number(_room_part_number : int = room_part_number):
|
|||||||
|
|
||||||
var shifted_origin = Vector3.LEFT * ROOM_PART_SHIFT * room_part_number/2
|
var shifted_origin = Vector3.LEFT * ROOM_PART_SHIFT * room_part_number/2
|
||||||
|
|
||||||
|
var incubator_id = 0
|
||||||
for i in range(room_part_number):
|
for i in range(room_part_number):
|
||||||
var new_room_part := ROOM_PART_SCENE.instantiate() as Node3D
|
var new_room_part := ROOM_PART_SCENE.instantiate() as Node3D
|
||||||
%RoomParts.add_child(new_room_part)
|
%RoomParts.add_child(new_room_part)
|
||||||
@@ -92,7 +105,9 @@ func set_room_part_number(_room_part_number : int = room_part_number):
|
|||||||
for j in range(INCUBATOR_BY_ROOM):
|
for j in range(INCUBATOR_BY_ROOM):
|
||||||
for direction in [-1, 1]:
|
for direction in [-1, 1]:
|
||||||
var new_incubator := INCUBATOR_SCENE.instantiate() as Incubator
|
var new_incubator := INCUBATOR_SCENE.instantiate() as Incubator
|
||||||
|
new_incubator.used = incubator_id in GameInfo.game_data.incubator_used
|
||||||
%Incubators.add_child(new_incubator)
|
%Incubators.add_child(new_incubator)
|
||||||
|
incubator_id += 1
|
||||||
new_incubator.position = (
|
new_incubator.position = (
|
||||||
new_room_part.position
|
new_room_part.position
|
||||||
+ j * Vector3.LEFT * (ROOM_PART_SHIFT / INCUBATOR_BY_ROOM)
|
+ j * Vector3.LEFT * (ROOM_PART_SHIFT / INCUBATOR_BY_ROOM)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ func _ready():
|
|||||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
|
|
||||||
await %Phone.clicked
|
await %Phone.clicked
|
||||||
Dialogic.start_timeline(OUTRO_TIMELINE_PATH)
|
Dialogic.start(OUTRO_TIMELINE_PATH)
|
||||||
await Dialogic.timeline_ended
|
await Dialogic.timeline_ended
|
||||||
%Credits.show()
|
%Credits.show()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
|
const DIALOG_PATH = "res://dialogs/timelines/story/demeter_ship_presentation.dtl"
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready():
|
||||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
|
|
||||||
|
%Phone.play_audio()
|
||||||
|
await %Phone.clicked
|
||||||
|
Dialogic.start(DIALOG_PATH)
|
||||||
|
await Dialogic.timeline_ended
|
||||||
|
SceneManager.change_to_scene_id("COCKPIT")
|
||||||
|
|||||||
@@ -147,4 +147,5 @@ omni_range = 21.258795
|
|||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.37195766, 2.8968668, -0.44411802)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.37195766, 2.8968668, -0.44411802)
|
||||||
|
|
||||||
[node name="Phone" parent="." unique_id=429299908 instance=ExtResource("7_dkh4e")]
|
[node name="Phone" parent="." unique_id=429299908 instance=ExtResource("7_dkh4e")]
|
||||||
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(-0.83126587, 0, -0.555875, 0, 1, 0, 0.555875, 0, -0.83126587, -4.110002, 1.6397171, 6.610814)
|
transform = Transform3D(-0.83126587, 0, -0.555875, 0, 1, 0, 0.555875, 0, -0.83126587, -4.110002, 1.6397171, 6.610814)
|
||||||
|
|||||||
@@ -1,10 +1,58 @@
|
|||||||
[gd_scene format=3 uid="uid://d0n52psuns1vl"]
|
[gd_scene format=3 uid="uid://d0n52psuns1vl"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://ddf3fktoer2ng" path="res://stages/intro/scripts/intro.gd" id="1_2nxbv"]
|
[ext_resource type="Script" uid="uid://ddf3fktoer2ng" path="res://stages/intro/scripts/intro.gd" id="1_2nxbv"]
|
||||||
|
[ext_resource type="Shader" uid="uid://bv2rghn44mrrf" path="res://stages/title_screen/resources/shaders/stars.gdshader" id="2_851lr"]
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2nxbv"]
|
||||||
|
shader = ExtResource("2_851lr")
|
||||||
|
shader_parameter/sky_color = Color(0.03, 0.05, 0.11, 1)
|
||||||
|
shader_parameter/star_base_color = Color(0.8, 1, 0.3, 1)
|
||||||
|
shader_parameter/star_hue_offset = 0.6
|
||||||
|
shader_parameter/star_intensity = 0.08
|
||||||
|
shader_parameter/star_twinkle_speed = 0.8
|
||||||
|
shader_parameter/star_twinkle_intensity = 0.2
|
||||||
|
shader_parameter/layer_scale = 20.0
|
||||||
|
shader_parameter/layer_scale_step = 10.0
|
||||||
|
shader_parameter/layers_count = 3
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_65b6a"]
|
||||||
|
sky_material = SubResource("ShaderMaterial_2nxbv")
|
||||||
|
|
||||||
|
[sub_resource type="Environment" id="Environment_mi20s"]
|
||||||
|
background_mode = 2
|
||||||
|
sky = SubResource("Sky_65b6a")
|
||||||
|
sky_custom_fov = 61.7
|
||||||
|
ambient_light_source = 3
|
||||||
|
ambient_light_color = Color(1, 1, 1, 1)
|
||||||
|
ambient_light_sky_contribution = 0.85
|
||||||
|
ambient_light_energy = 2.0
|
||||||
|
reflected_light_source = 2
|
||||||
|
tonemap_mode = 2
|
||||||
|
tonemap_exposure = 0.7
|
||||||
|
tonemap_white = 1.84
|
||||||
|
glow_enabled = true
|
||||||
|
glow_intensity = 0.22
|
||||||
|
glow_bloom = 0.22
|
||||||
|
glow_hdr_threshold = 0.79
|
||||||
|
glow_hdr_scale = 0.0
|
||||||
|
glow_hdr_luminance_cap = 5.63
|
||||||
|
fog_enabled = true
|
||||||
|
fog_mode = 1
|
||||||
|
fog_light_color = Color(0.13725491, 0.39215687, 0.6666667, 1)
|
||||||
|
fog_density = 0.1831
|
||||||
|
fog_aerial_perspective = 0.113
|
||||||
|
fog_sky_affect = 0.0
|
||||||
|
volumetric_fog_sky_affect = 0.0
|
||||||
|
adjustment_enabled = true
|
||||||
|
adjustment_saturation = 1.3
|
||||||
|
|
||||||
[node name="Intro" type="Node" unique_id=1801844904]
|
[node name="Intro" type="Node" unique_id=1801844904]
|
||||||
script = ExtResource("1_2nxbv")
|
script = ExtResource("1_2nxbv")
|
||||||
game_scene_path = "uid://d28cp7a21kwou"
|
game_scene_path = "uid://d28cp7a21kwou"
|
||||||
|
|
||||||
[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=1051527956]
|
[node name="Node3D" type="Node3D" parent="." unique_id=1668131521]
|
||||||
layer = 100
|
|
||||||
|
[node name="Camera3D" type="Camera3D" parent="Node3D" unique_id=2070854508]
|
||||||
|
|
||||||
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="Node3D" unique_id=115692868]
|
||||||
|
environment = SubResource("Environment_mi20s")
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
[ext_resource type="PackedScene" uid="uid://yk78ubpu5ghq" path="res://gui/game/pass_day/pass_day.tscn" id="3_ktnx3"]
|
[ext_resource type="PackedScene" uid="uid://yk78ubpu5ghq" path="res://gui/game/pass_day/pass_day.tscn" id="3_ktnx3"]
|
||||||
[ext_resource type="PackedScene" uid="uid://12nak7amd1uq" path="res://gui/game/game_gui.tscn" id="4_qdnee"]
|
[ext_resource type="PackedScene" uid="uid://12nak7amd1uq" path="res://gui/game/game_gui.tscn" id="4_qdnee"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bgvbgeq46wee2" path="res://entities/player/player.tscn" id="5_ovqi1"]
|
[ext_resource type="PackedScene" uid="uid://bgvbgeq46wee2" path="res://entities/player/player.tscn" id="5_ovqi1"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cg1visg52i21a" path="res://entities/interactables/ladder/ladder.tscn" id="6_2w03p"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://d324mlmgls4fs" path="res://entities/interactables/truck/recharge/truck_recharge.tscn" id="7_6d8m3"]
|
[ext_resource type="PackedScene" uid="uid://d324mlmgls4fs" path="res://entities/interactables/truck/recharge/truck_recharge.tscn" id="7_6d8m3"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b8m537op75gib" path="res://entities/interactables/door/door.tscn" id="8_2f6js"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dj7gp3crtg2yt" path="res://entities/camera/camera.tscn" id="8_fwgig"]
|
[ext_resource type="PackedScene" uid="uid://dj7gp3crtg2yt" path="res://entities/camera/camera.tscn" id="8_fwgig"]
|
||||||
|
|
||||||
[node name="Region" type="Node2D" unique_id=1509166288 node_paths=PackedStringArray("entity_container")]
|
[node name="Region" type="Node2D" unique_id=1509166288 node_paths=PackedStringArray("entity_container")]
|
||||||
@@ -28,14 +28,31 @@ region = NodePath("../..")
|
|||||||
[node name="Entities" type="Node2D" parent="." unique_id=2132324579]
|
[node name="Entities" type="Node2D" parent="." unique_id=2132324579]
|
||||||
y_sort_enabled = true
|
y_sort_enabled = true
|
||||||
|
|
||||||
[node name="TruckLadder" parent="Entities" unique_id=1990299618 instance=ExtResource("6_2w03p")]
|
|
||||||
position = Vector2(51, -112)
|
|
||||||
|
|
||||||
[node name="Player" parent="Entities" unique_id=75851644 instance=ExtResource("5_ovqi1")]
|
[node name="Player" parent="Entities" unique_id=75851644 instance=ExtResource("5_ovqi1")]
|
||||||
z_index = 1
|
z_index = 1
|
||||||
|
position = Vector2(3000, -41)
|
||||||
|
|
||||||
[node name="TruckRecharge" parent="Entities" unique_id=2068738444 instance=ExtResource("7_6d8m3")]
|
[node name="TruckRecharge" parent="Entities" unique_id=2068738444 instance=ExtResource("7_6d8m3")]
|
||||||
position = Vector2(-50, -124)
|
position = Vector2(-1, -169)
|
||||||
|
|
||||||
|
[node name="AstraDoor" parent="Entities" unique_id=2053096538 instance=ExtResource("8_2f6js")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
modulate = Color(1, 0, 0, 1)
|
||||||
|
position = Vector2(-43, 367)
|
||||||
|
available = false
|
||||||
|
default_info_title = "ASTRA_FACTORY"
|
||||||
|
default_info_desc = "ASTRA_FACTORY_TEXT"
|
||||||
|
|
||||||
|
[node name="ShipGarageDoor" parent="Entities" unique_id=1073871193 instance=ExtResource("8_2f6js")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
modulate = Color(1, 0, 0, 1)
|
||||||
|
to_scene_id = "GARAGE"
|
||||||
|
default_interact_text = "ENTER"
|
||||||
|
available = false
|
||||||
|
default_info_title = "MYSTERIOUS_DOOR"
|
||||||
|
default_info_desc = "MYSTERIOUS_DOOR_TEXT"
|
||||||
|
|
||||||
[node name="Camera" parent="." unique_id=1399042986 node_paths=PackedStringArray("following") instance=ExtResource("8_fwgig")]
|
[node name="Camera" parent="." unique_id=1399042986 node_paths=PackedStringArray("following") instance=ExtResource("8_fwgig")]
|
||||||
following = NodePath("../Entities/Player")
|
following = NodePath("../Entities/Player")
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const TILE_SET : TileSet = preload("res://stages/terrain/region/resources/moss_b
|
|||||||
const TILE_SCALE = 1
|
const TILE_SCALE = 1
|
||||||
const TILE_SIZE : int = roundi(TILE_SET.tile_size.x * TILE_SCALE)
|
const TILE_SIZE : int = roundi(TILE_SET.tile_size.x * TILE_SCALE)
|
||||||
const START_ROCK_HOLE_RADIUS = 5
|
const START_ROCK_HOLE_RADIUS = 5
|
||||||
|
const PLAYER_ROCK_HOLE_RADIUS = 5
|
||||||
const START_DECONTAMINATION_HOLE_RADIUS = 3
|
const START_DECONTAMINATION_HOLE_RADIUS = 3
|
||||||
const CHUNK_TILE_SIZE : int = 20
|
const CHUNK_TILE_SIZE : int = 20
|
||||||
const CHUNK_SIZE = CHUNK_TILE_SIZE * TILE_SIZE
|
const CHUNK_SIZE = CHUNK_TILE_SIZE * TILE_SIZE
|
||||||
@@ -69,8 +70,6 @@ func _ready():
|
|||||||
if e is Plant:
|
if e is Plant:
|
||||||
data.add_plant_data(e.data, false)
|
data.add_plant_data(e.data, false)
|
||||||
|
|
||||||
generate_first_entities()
|
|
||||||
|
|
||||||
ground_layer = GroundLayer.new(self)
|
ground_layer = GroundLayer.new(self)
|
||||||
add_child(ground_layer)
|
add_child(ground_layer)
|
||||||
rock_layer = RockLayer.new(self)
|
rock_layer = RockLayer.new(self)
|
||||||
@@ -91,11 +90,6 @@ func _process(_d):
|
|||||||
|
|
||||||
#region ------------------ Generation ------------------
|
#region ------------------ Generation ------------------
|
||||||
|
|
||||||
func generate_first_entities():
|
|
||||||
if not (Vector2i.ZERO in data.generated_chunk_entities):
|
|
||||||
# Generate shovel
|
|
||||||
drop_item(Shovel.new(), entity_container.global_position + Vector2(0, 100))
|
|
||||||
|
|
||||||
func get_chunk_key(coord) -> String:
|
func get_chunk_key(coord) -> String:
|
||||||
return "%d:%d" % [coord.x, coord.y]
|
return "%d:%d" % [coord.x, coord.y]
|
||||||
|
|
||||||
@@ -150,6 +144,21 @@ func edit_map_origin():
|
|||||||
rock_layer.remove_rocks(hole_tiles, true)
|
rock_layer.remove_rocks(hole_tiles, true)
|
||||||
decontamination_layer.place_decontaminations(decontamination_tiles, true)
|
decontamination_layer.place_decontaminations(decontamination_tiles, true)
|
||||||
|
|
||||||
|
# Dig a hole in player position
|
||||||
|
var player_hole_tiles : Array[Vector2i] = []
|
||||||
|
var player_tile_position := Vector2i(
|
||||||
|
roundi(data.player_position.x/float(TILE_SIZE)),
|
||||||
|
roundi(data.player_position.y/float(TILE_SIZE))
|
||||||
|
)
|
||||||
|
for x in range(-PLAYER_ROCK_HOLE_RADIUS, PLAYER_ROCK_HOLE_RADIUS):
|
||||||
|
for y in range(-PLAYER_ROCK_HOLE_RADIUS, PLAYER_ROCK_HOLE_RADIUS):
|
||||||
|
var coord = Vector2i(x,y)
|
||||||
|
if coord.distance_to(Vector2.ZERO) < PLAYER_ROCK_HOLE_RADIUS:
|
||||||
|
player_hole_tiles.append(coord + player_tile_position)
|
||||||
|
rock_layer.remove_rocks(player_hole_tiles, true)
|
||||||
|
|
||||||
|
setup_tutorial_doors()
|
||||||
|
|
||||||
func remove_chunk(chunk : Chunk):
|
func remove_chunk(chunk : Chunk):
|
||||||
generated_chunks.erase(get_chunk_key(chunk.data.chunk_coord))
|
generated_chunks.erase(get_chunk_key(chunk.data.chunk_coord))
|
||||||
chunk.unload()
|
chunk.unload()
|
||||||
@@ -179,6 +188,18 @@ func save():
|
|||||||
data.player_position = player.global_position
|
data.player_position = player.global_position
|
||||||
GameInfo.save_game_data()
|
GameInfo.save_game_data()
|
||||||
|
|
||||||
|
func setup_tutorial_doors():
|
||||||
|
%AstraDoor.visible = data.tutorial
|
||||||
|
%ShipGarageDoor.visible = data.tutorial
|
||||||
|
if data.tutorial:
|
||||||
|
%AstraDoor.global_position = data.get_random_spawn_position()
|
||||||
|
%AstraDoor.available = false
|
||||||
|
%ShipGarageDoor.available = data.state == RegionData.State.SUCCEEDED
|
||||||
|
data.succeded.connect(
|
||||||
|
func ():
|
||||||
|
%ShipGarageDoor.available = true
|
||||||
|
)
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ------------------ Usage ------------------
|
#region ------------------ Usage ------------------
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ signal pass_day_ended(region_data : RegionData)
|
|||||||
|
|
||||||
const DEFAULT_START_CHARGE := 10
|
const DEFAULT_START_CHARGE := 10
|
||||||
const DEFAULT_OBJECTIVE := 10
|
const DEFAULT_OBJECTIVE := 10
|
||||||
|
const MAX_RANDOM_SPAWN_DISTANCE = 3000
|
||||||
|
|
||||||
@export var region_seed : int
|
@export var region_seed : int
|
||||||
@export var region_name : String
|
@export var region_name : String
|
||||||
@@ -31,7 +32,7 @@ const DEFAULT_OBJECTIVE := 10
|
|||||||
|
|
||||||
@export var chunks_data : Dictionary[String, ChunkData]
|
@export var chunks_data : Dictionary[String, ChunkData]
|
||||||
|
|
||||||
@export var player_position : Vector2i = Region.CHUNK_SIZE/2. * Vector2.ONE
|
@export var player_position : Vector2i = Region.CHUNK_SIZE/2. * Vector2.ONE + get_random_spawn_position()
|
||||||
|
|
||||||
@export var charges : int :
|
@export var charges : int :
|
||||||
set(v):
|
set(v):
|
||||||
@@ -81,7 +82,9 @@ func add_chunk_data(coord : Vector2i, data : ChunkData):
|
|||||||
chunks_data[get_coord_id(coord)] = data
|
chunks_data[get_coord_id(coord)] = data
|
||||||
|
|
||||||
func get_chunk_data(coord : Vector2i) -> ChunkData:
|
func get_chunk_data(coord : Vector2i) -> ChunkData:
|
||||||
return chunks_data[get_coord_id(coord)]
|
if get_coord_id(coord) in chunks_data:
|
||||||
|
return chunks_data[get_coord_id(coord)]
|
||||||
|
return null
|
||||||
|
|
||||||
func get_or_create_chunk_data(coord : Vector2i) -> ChunkData:
|
func get_or_create_chunk_data(coord : Vector2i) -> ChunkData:
|
||||||
if has_chunk_data(coord):
|
if has_chunk_data(coord):
|
||||||
@@ -147,3 +150,13 @@ func _on_plant_disappeared(plant_data : PlantData):
|
|||||||
update()
|
update()
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
func get_random_spawn_position():
|
||||||
|
var rng := RandomNumberGenerator.new()
|
||||||
|
rng.seed = region_seed
|
||||||
|
|
||||||
|
return Vector2(
|
||||||
|
rng.randf_range(-MAX_RANDOM_SPAWN_DISTANCE,MAX_RANDOM_SPAWN_DISTANCE),
|
||||||
|
rng.randf_range(-MAX_RANDOM_SPAWN_DISTANCE,MAX_RANDOM_SPAWN_DISTANCE),
|
||||||
|
)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func place_decontaminations(coords : Array[Vector2i], save := false, on_finished
|
|||||||
floori(coord.y / float(Region.CHUNK_TILE_SIZE)),
|
floori(coord.y / float(Region.CHUNK_TILE_SIZE)),
|
||||||
)
|
)
|
||||||
(region.data
|
(region.data
|
||||||
.get_chunk_data(chunk_coord)
|
.get_or_create_chunk_data(chunk_coord)
|
||||||
.update_decontamination_tile_diff(coord, ChunkData.TileDiff.PRESENT))
|
.update_decontamination_tile_diff(coord, ChunkData.TileDiff.PRESENT))
|
||||||
|
|
||||||
func is_decontamined(coord : Vector2i) -> bool:
|
func is_decontamined(coord : Vector2i) -> bool:
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func remove_rocks(coords : Array[Vector2i], save = false,on_finished : Callable
|
|||||||
)
|
)
|
||||||
var chunk_tile_coord : Vector2i = coord - chunk_coord * Region.CHUNK_TILE_SIZE
|
var chunk_tile_coord : Vector2i = coord - chunk_coord * Region.CHUNK_TILE_SIZE
|
||||||
(region.data
|
(region.data
|
||||||
.get_chunk_data(chunk_coord)
|
.get_or_create_chunk_data(chunk_coord)
|
||||||
.update_rock_tile_diff(chunk_tile_coord, ChunkData.TileDiff.ABSENT))
|
.update_rock_tile_diff(chunk_tile_coord, ChunkData.TileDiff.ABSENT))
|
||||||
|
|
||||||
func dig_rocks(coords : Array[Vector2i]) -> bool:
|
func dig_rocks(coords : Array[Vector2i]) -> bool:
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ ONE_TIME_USE,Single use,Usage unique
|
|||||||
BUILD_%s,Build %s,Construit %s
|
BUILD_%s,Build %s,Construit %s
|
||||||
FORK,Fork,Fourche
|
FORK,Fork,Fourche
|
||||||
FORK_DESC_TEXT,"Use it to [b]harvest mature plants[/b].","Utilise-la pour [b]récolter les plantes mature[/b]."
|
FORK_DESC_TEXT,"Use it to [b]harvest mature plants[/b].","Utilise-la pour [b]récolter les plantes mature[/b]."
|
||||||
|
DETECTOR,Detector,Détecteur
|
||||||
|
DETECTOR_DESC_TEXT,"Indicate [b]near signals[/b].","Indique les [b]signaux proches[/b]"
|
||||||
|
DETECT_USE_TEXT,"Search near signals","Rechercher les signaux proches"
|
||||||
HARVEST,Harvest,Récolter
|
HARVEST,Harvest,Récolter
|
||||||
KNIFE,Knife,Couteau
|
KNIFE,Knife,Couteau
|
||||||
KNIFE_DESC_TEXT,"Use it to [b]harvest mature plants[/b]. Does not consume energy.",Utilise-le pour [b]récolter les plantes mature[/b]. Ne consomme pas d’énergie.
|
KNIFE_DESC_TEXT,"Use it to [b]harvest mature plants[/b]. Does not consume energy.",Utilise-le pour [b]récolter les plantes mature[/b]. Ne consomme pas d’énergie.
|
||||||
@@ -115,7 +118,7 @@ SCORE_%d,Score %d,Score %d
|
|||||||
SOLAR_PANNEL,Solar panel,Panneau solaire
|
SOLAR_PANNEL,Solar panel,Panneau solaire
|
||||||
SOLAR_PANNEL_DESCRIPTION_TEXT,Grants energy when charged. Take several days to recharge,Donne de l’énergie quand chargé. Prend plusieurs jours à se recharger
|
SOLAR_PANNEL_DESCRIPTION_TEXT,Grants energy when charged. Take several days to recharge,Donne de l’énergie quand chargé. Prend plusieurs jours à se recharger
|
||||||
TRUCK_ENTRANCE,Truck entrance,Entrée du camion
|
TRUCK_ENTRANCE,Truck entrance,Entrée du camion
|
||||||
ENTER_TRUCK,Enter truck,Entrer dans le camion
|
ENTER,Enter,Entrer
|
||||||
EXIT,Exit,Sortie
|
EXIT,Exit,Sortie
|
||||||
EXIT_TRUCK,Exit truck,Sortir du camion
|
EXIT_TRUCK,Exit truck,Sortir du camion
|
||||||
LADDER_DESC_TEXT,A good old ladder,Une bonne vieille échelle
|
LADDER_DESC_TEXT,A good old ladder,Une bonne vieille échelle
|
||||||
@@ -197,4 +200,8 @@ MUSIC_SOUND_DESIGN_AND_WRITING,"Music, Sound design and Wrinting","Musique, Sons
|
|||||||
COMMUNICATION,"Communication","Communication"
|
COMMUNICATION,"Communication","Communication"
|
||||||
SPLASH_ART,Splash Art,Splash Art
|
SPLASH_ART,Splash Art,Splash Art
|
||||||
TRAILER,"Trailer","Trailer"
|
TRAILER,"Trailer","Trailer"
|
||||||
CREDITS,Credits,Crédits
|
CREDITS,Credits,Crédits
|
||||||
|
ASTRA_FACTORY,Astra Factory,Usine Astra
|
||||||
|
ASTRA_FACTORY_TEXT,Production factory of Astra base,Usine de production de la base Astra
|
||||||
|
MYSTERIOUS_DOOR,Mysterious Door,Porte mystérieuse
|
||||||
|
MYSTERIOUS_DOOR_TEXT,"This door has a space ship logo on it... What could it be ?","Cette porte à un logo de vaisseau marqué dessus... Que peut-il y avoir à l'intérieur ?"
|
||||||
|
Reference in New Issue
Block a user