base addon version?

This commit is contained in:
pennyrigate 2025-03-01 16:39:50 -05:00
commit 8e56975f09
21 changed files with 1304 additions and 0 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
# Godot 4+ specific ignores
.godot/
/android/
addons/dialogue_manager/

82
README.md Normal file
View file

@ -0,0 +1,82 @@
Thank you for using DVN!
DVN is a Godot Visual novel example project.
If you need help using features of DVN, click "Search Help" on the Top Left of
the middle editor window (to the left of "Inspector")
DVN is made up of 3 new classes:
- DVNScene: The class that contains all the functions that DVN uses, every scene
should inherit from this class, as well as dvn.tscn. If you want to make a new scene,
press ctrl+shift+N (or click scene>new inherited scene) and choose to inherit from dvn.tscn.
you can edit your inherited scene to your heart's content, but editing dvn.tscn itself, or dvn.gd will
change the way DVN itself works. If you want to add to DVNScene's functions, feel free to. You can also just
call super() and then run your custom code.
etc.
# In your scene vvv
func create_text_balloon():
super()
#YOUR ADDITIONAL CODE HERE
-DVNLabel: An extension of Godot Dialogue Manager's DialogueLabel compatible
with talktones and autotext.
Within your Balloon scene you can set exports for talktones, voice clips, autotext etc.
You shouldn't be needing to call anything from here,
but if you have trouble with the way your dialogue is being drawn, feel free to check
how it works.
-DVNBalloon: A copy of Godot Dialogue Manager's default balloon, configured to work
with DVNLabels as well as DialogueLabels. There's a region in the script for label references,
feel free to add them there (you can also add them to your scene's script, or a global script).
You can also edit dvn_balloon.gd yourself, it's highly recommended you make a copy and edit it if
you want your baloon running custom code.
DVN is simply an add on to an addon. You can make new classes and shit if you want.
Keep and mind i will be updating DVN through git if needed, so i recommend you dont edit anything within
the DVN folder, unless you're willing to resolve conflicts.
Dialogue is handled by Nathan Hoad's "Godot Dialogue Manager" extension
for help with anything related to the Godot Dialogue Manager, consult its GitHub page
https://github.com/nathanhoad/godot_dialogue_manager
For help with anything Godot related, check the documentation.
Either by clicking "Search Help" in the top right of the script editor,
By right clicking a node type, or by going to
https://docs.godotengine.org/en/stable/
DVN is made for Godot 4.3, keep in mind there are major differences between
Godot 4 and Godot 3. Mostly function names.
DVN is CC0 open source <------ lame way of saying, use my code i dont care what you do with it, and you dont need to credit me
my name is TY TIRAMISU, if you do want to credit me :>
as for the Godot Dialogue Manager?
MIT License
Copyright (c) 2022-present Nathan Hoad and Dialogue Manager contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

82
addons/dvn/README.md Normal file
View file

@ -0,0 +1,82 @@
Thank you for using DVN!
DVN is a Godot Visual novel example project.
If you need help using features of DVN, click "Search Help" on the Top Left of
the middle editor window (to the left of "Inspector")
DVN is made up of 3 new classes:
- DVNScene: The class that contains all the functions that DVN uses, every scene
should inherit from this class, as well as dvn.tscn. If you want to make a new scene,
press ctrl+shift+N (or click scene>new inherited scene) and choose to inherit from dvn.tscn.
you can edit your inherited scene to your heart's content, but editing dvn.tscn itself, or dvn.gd will
change the way DVN itself works. If you want to add to DVNScene's functions, feel free to. You can also just
call super() and then run your custom code.
etc.
# In your scene vvv
func create_text_balloon():
super()
#YOUR ADDITIONAL CODE HERE
-DVNLabel: An extension of Godot Dialogue Manager's DialogueLabel compatible
with talktones and autotext.
Within your Balloon scene you can set exports for talktones, voice clips, autotext etc.
You shouldn't be needing to call anything from here,
but if you have trouble with the way your dialogue is being drawn, feel free to check
how it works.
-DVNBalloon: A copy of Godot Dialogue Manager's default balloon, configured to work
with DVNLabels as well as DialogueLabels. There's a region in the script for label references,
feel free to add them there (you can also add them to your scene's script, or a global script).
You can also edit dvn_balloon.gd yourself, it's highly recommended you make a copy and edit it if
you want your baloon running custom code.
DVN is simply an add on to an addon. You can make new classes and shit if you want.
Keep and mind i will be updating DVN through git if needed, so i recommend you dont edit anything within
the DVN folder, unless you're willing to resolve conflicts.
Dialogue is handled by Nathan Hoad's "Godot Dialogue Manager" extension
for help with anything related to the Godot Dialogue Manager, consult its GitHub page
https://github.com/nathanhoad/godot_dialogue_manager
For help with anything Godot related, check the documentation.
Either by clicking "Search Help" in the top right of the script editor,
By right clicking a node type, or by going to
https://docs.godotengine.org/en/stable/
DVN is made for Godot 4.3, keep in mind there are major differences between
Godot 4 and Godot 3. Mostly function names.
DVN is CC0 open source <------ lame way of saying, use my code i dont care what you do with it, and you dont need to credit me
my name is TY TIRAMISU, if you do want to credit me :>
as for the Godot Dialogue Manager?
MIT License
Copyright (c) 2022-present Nathan Hoad and Dialogue Manager contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

82
addons/dvn/README.txt Normal file
View file

@ -0,0 +1,82 @@
Thank you for using DVN!
DVN is a Godot Visual novel example project.
If you need help using features of DVN, click "Search Help" on the Top Left of
the middle editor window (to the left of "Inspector")
DVN is made up of 3 new classes:
- DVNScene: The class that contains all the functions that DVN uses, every scene
should inherit from this class, as well as dvn.tscn. If you want to make a new scene,
press ctrl+shift+N (or click scene>new inherited scene) and choose to inherit from dvn.tscn.
you can edit your inherited scene to your heart's content, but editing dvn.tscn itself, or dvn.gd will
change the way DVN itself works. If you want to add to DVNScene's functions, feel free to. You can also just
call super() and then run your custom code.
etc.
# In your scene vvv
func create_text_balloon():
super()
#YOUR ADDITIONAL CODE HERE
-DVNLabel: An extension of Godot Dialogue Manager's DialogueLabel compatible
with talktones and autotext.
Within your Balloon scene you can set exports for talktones, voice clips, autotext etc.
You shouldn't be needing to call anything from here,
but if you have trouble with the way your dialogue is being drawn, feel free to check
how it works.
-DVNBalloon: A copy of Godot Dialogue Manager's default balloon, configured to work
with DVNLabels as well as DialogueLabels. There's a region in the script for label references,
feel free to add them there (you can also add them to your scene's script, or a global script).
You can also edit dvn_balloon.gd yourself, it's highly recommended you make a copy and edit it if
you want your baloon running custom code.
DVN is simply an add on to an addon. You can make new classes and shit if you want.
Keep and mind i will be updating DVN through git if needed, so i recommend you dont edit anything within
the DVN folder, unless you're willing to resolve conflicts.
Dialogue is handled by Nathan Hoad's "Godot Dialogue Manager" extension
for help with anything related to the Godot Dialogue Manager, consult its GitHub page
https://github.com/nathanhoad/godot_dialogue_manager
For help with anything Godot related, check the documentation.
Either by clicking "Search Help" in the top right of the script editor,
By right clicking a node type, or by going to
https://docs.godotengine.org/en/stable/
DVN is made for Godot 4.3, keep in mind there are major differences between
Godot 4 and Godot 3. Mostly function names.
DVN is CC0 open source <------ lame way of saying, use my code i dont care what you do with it, and you dont need to credit me
my name is TY TIRAMISU, if you do want to credit me :>
as for the Godot Dialogue Manager?
MIT License
Copyright (c) 2022-present Nathan Hoad and Dialogue Manager contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,182 @@
class_name DVNBalloon extends CanvasLayer
## A basic dialogue balloon for use with Dialogue Manager.
## The initial label to spit text out from
@export var label:NodePath
## The action to use for advancing the dialogue
@export var next_action: StringName = &"ui_accept"
## The action to use to skip typing the dialogue
@export var skip_action: StringName = &"ui_cancel"
## The dialogue resource
var resource: DialogueResource
## Temporary game states
var temporary_game_states: Array = []
## See if we are waiting for the player
var is_waiting_for_input: bool = false
## See if we are running a long mutation and should hide the balloon
var will_hide_balloon: bool = false
## A dictionary to store any ephemeral variables
var locals: Dictionary = {}
var _locale: String = TranslationServer.get_locale()
## The current line
var dialogue_line: DialogueLine:
set(value):
if value:
dialogue_line = value
apply_dialogue_line()
else:
# The dialogue has finished so close the balloon
queue_free()
get:
return dialogue_line
## A cooldown timer for delaying the balloon hide when encountering a mutation.
var mutation_cooldown: Timer = Timer.new()
## The base balloon anchor
@onready var balloon: Control = %Balloon
## The label showing the name of the currently speaking character
@onready var character_label: RichTextLabel = %CharacterLabel
## The label showing the currently spoken dialogue
@onready var dialogue_label: DVNLabel = get_node(label)
## The menu of responses
@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu
#region Label References
#Put label references here
#endregion
func _ready() -> void:
balloon.hide()
Engine.get_singleton("DialogueManager").mutated.connect(_on_mutated)
# If the responses menu doesn't have a next action set, use this one
if responses_menu.next_action.is_empty():
responses_menu.next_action = next_action
mutation_cooldown.timeout.connect(_on_mutation_cooldown_timeout)
add_child(mutation_cooldown)
func _unhandled_input(_event: InputEvent) -> void:
# Only the balloon is allowed to handle input while it's showing
get_viewport().set_input_as_handled()
func _notification(what: int) -> void:
## Detect a change of locale and update the current dialogue line to show the new language
if what == NOTIFICATION_TRANSLATION_CHANGED and _locale != TranslationServer.get_locale() and is_instance_valid(dialogue_label):
_locale = TranslationServer.get_locale()
var visible_ratio = dialogue_label.visible_ratio
self.dialogue_line = await resource.get_next_dialogue_line(dialogue_line.id)
if visible_ratio < 1:
dialogue_label.skip_typing()
## Start some dialogue
func start(dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []) -> void:
temporary_game_states = [self] + extra_game_states
is_waiting_for_input = false
resource = dialogue_resource
self.dialogue_line = await resource.get_next_dialogue_line(title, temporary_game_states)
## Apply any changes to the balloon given a new [DialogueLine].
func apply_dialogue_line() -> void:
mutation_cooldown.stop()
is_waiting_for_input = false
balloon.focus_mode = Control.FOCUS_ALL
balloon.grab_focus()
character_label.visible = not dialogue_line.character.is_empty()
character_label.text = tr(dialogue_line.character, "dialogue")
dialogue_label.hide()
dialogue_label.dialogue_line = dialogue_line
responses_menu.hide()
responses_menu.responses = dialogue_line.responses
# Show our balloon
balloon.show()
will_hide_balloon = false
dialogue_label.show()
if not dialogue_line.text.is_empty():
dialogue_label.type_out()
await dialogue_label.finished_typing
# Wait for input
if dialogue_line.responses.size() > 0:
balloon.focus_mode = Control.FOCUS_NONE
responses_menu.show()
elif dialogue_line.time != "":
var time = dialogue_line.text.length() * 0.02 if dialogue_line.time == "auto" else dialogue_line.time.to_float()
await get_tree().create_timer(time).timeout
next(dialogue_line.next_id)
else:
is_waiting_for_input = true
balloon.focus_mode = Control.FOCUS_ALL
balloon.grab_focus()
## Go to the next line
func next(next_id: String) -> void:
self.dialogue_line = await resource.get_next_dialogue_line(next_id, temporary_game_states)
#region Signals
func _on_mutation_cooldown_timeout() -> void:
if will_hide_balloon:
will_hide_balloon = false
balloon.hide()
func _on_mutated(_mutation: Dictionary) -> void:
is_waiting_for_input = false
will_hide_balloon = true
mutation_cooldown.start(0.1)
func _on_balloon_gui_input(event: InputEvent) -> void:
# See if we need to skip typing of the dialogue
if dialogue_label.is_typing:
var mouse_was_clicked: bool = event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed()
var skip_button_was_pressed: bool = event.is_action_pressed(skip_action)
if mouse_was_clicked or skip_button_was_pressed:
get_viewport().set_input_as_handled()
dialogue_label.skip_typing()
return
if not is_waiting_for_input: return
if dialogue_line.responses.size() > 0: return
# When there are no response options the balloon itself is the clickable thing
get_viewport().set_input_as_handled()
if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT:
next(dialogue_line.next_id)
elif event.is_action_pressed(next_action) and get_viewport().gui_get_focus_owner() == balloon:
next(dialogue_line.next_id)
func _process(delta: float) -> void:
print(dialogue_line.responses.size())
func _on_responses_menu_response_selected(response: DialogueResponse) -> void:
next(response.next_id)
#endregion

View file

@ -0,0 +1,152 @@
[gd_scene load_steps=9 format=3 uid="uid://kssjsapnseux"]
[ext_resource type="Script" path="res://addons/dvn/balloon/dvn_balloon.gd" id="1_7pshc"]
[ext_resource type="PackedScene" uid="uid://cca3fm3pojb41" path="res://addons/dvn/label/dvn_label.tscn" id="2_7ceuc"]
[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_responses_menu.gd" id="3_72ixx"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_spyqn"]
bg_color = Color(0, 0, 0, 1)
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color(0.329412, 0.329412, 0.329412, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ri4m3"]
bg_color = Color(0.121569, 0.121569, 0.121569, 1)
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color(1, 1, 1, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e0njw"]
bg_color = Color(0, 0, 0, 1)
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color(0.6, 0.6, 0.6, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"]
bg_color = Color(0, 0, 0, 1)
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="Theme" id="Theme_qq3yp"]
default_font_size = 20
Button/styles/disabled = SubResource("StyleBoxFlat_spyqn")
Button/styles/focus = SubResource("StyleBoxFlat_ri4m3")
Button/styles/hover = SubResource("StyleBoxFlat_e0njw")
Button/styles/normal = SubResource("StyleBoxFlat_e0njw")
MarginContainer/constants/margin_bottom = 15
MarginContainer/constants/margin_left = 30
MarginContainer/constants/margin_right = 30
MarginContainer/constants/margin_top = 15
Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5")
[node name="DVNBalloon" type="CanvasLayer"]
layer = 100
script = ExtResource("1_7pshc")
label = NodePath("Balloon/Panel/Dialogue/VBoxContainer/DVNLabel")
[node name="Balloon" type="Control" parent="."]
unique_name_in_owner = true
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("Theme_qq3yp")
[node name="Panel" type="Panel" parent="Balloon"]
clip_children = 2
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 21.0
offset_top = -183.0
offset_right = -19.0
offset_bottom = -19.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 1
[node name="Dialogue" type="MarginContainer" parent="Balloon/Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="Balloon/Panel/Dialogue"]
layout_mode = 2
[node name="CharacterLabel" type="RichTextLabel" parent="Balloon/Panel/Dialogue/VBoxContainer"]
unique_name_in_owner = true
modulate = Color(1, 1, 1, 0.501961)
layout_mode = 2
mouse_filter = 1
bbcode_enabled = true
text = "Character"
fit_content = true
scroll_active = false
[node name="DVNLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_7ceuc")]
unique_name_in_owner = true
layout_mode = 2
talktone_player_path = NodePath("../../../../../TalktonePlayer")
[node name="Responses" type="MarginContainer" parent="Balloon"]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -147.0
offset_top = -558.0
offset_right = 494.0
offset_bottom = -154.0
grow_horizontal = 2
grow_vertical = 0
[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses" node_paths=PackedStringArray("response_template")]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 8
theme_override_constants/separation = 2
script = ExtResource("3_72ixx")
response_template = NodePath("ResponseExample")
[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"]
layout_mode = 2
text = "Response example"
[node name="TalktonePlayer" type="AudioStreamPlayer" parent="."]
bus = &"VOX"
[connection signal="gui_input" from="Balloon" to="." method="_on_balloon_gui_input"]
[connection signal="response_selected" from="Balloon/Responses/ResponsesMenu" to="." method="_on_responses_menu_response_selected"]

View file

@ -0,0 +1,21 @@
[gd_resource type="AudioBusLayout" format=3 uid="uid://cv4d8sgujag0l"]
[resource]
bus/1/name = &"BGM"
bus/1/solo = false
bus/1/mute = false
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/2/name = &"SFX"
bus/2/solo = false
bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"
bus/3/name = &"VOX"
bus/3/solo = false
bus/3/mute = false
bus/3/bypass_fx = false
bus/3/volume_db = 0.0
bus/3/send = &"Master"

316
addons/dvn/dvn.gd Normal file
View file

@ -0,0 +1,316 @@
@icon("dvn.png")
class_name DVNScene extends Node2D
## The DVNScene Node contains all of the built in functions of DVN, excluding those affecting text.
## Every scene in the DVN engine should extend DVNScene, imagine it as a base scene.
## Completely Invisible Color, if the alpha is increased it becomes [member Color.WHITE]
const TRANS_WHITE = Color(1,1,1,0)
## Completely Invisible Color, if the alpha is increased it becomes [member Color.BLACK]
const TRANS_BLACK = Color(0,0,0,0)
## Called when [method fade_out_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
signal screen_fade_out
## Called when [method fade_in_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
signal screen_fade_in
## Called when [method fade_out_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade_out
## Called when [method fade_in_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade_in
## Called when [method fade_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade
## Called when [method delay] has counted all the way down.
signal delay_ended
## Called when the sound created by [method play_sound] has finished playing.
## [br]NOTE: Will only be called if [param async] is false!!!
signal sound_ended
## Default ballon to create with [method create_text_balloon]
@export var Balloon: PackedScene = null
## Default ballon to start with [method create_text_balloon]
@export var Dialogue: DialogueResource = null
## Set the current dialogue automation type.
## [br]see [enum DialogueAutomationTypes] for more info
@export_enum("Manual", "Auto Text", "Auto Voice") var dialogue_automation_type: int
## [param] MANUAL is the default way of handling text. The next line of dialogue is not
## drawn until the user inputs a command.
## [br][param AUTO_TEXT] Automatically skips to the next text box after the [member auto_text_delay] timer is done counting down.
## [br][param AUTO_VOICE] Automatically skips to the next text box when the voice clip is done playing.
enum DialogueAutomationTypes{MANUAL,AUTO_TEXT,AUTO_VOICE}
## The wait time until new text is drawn when [member dialogue_automation_type] is set to auto voice.
@export var auto_text_delay:float = 1.0
## Default time value for fading the screen
@export var default_screen_fade_time: float = 2.0
## Default time value for fading the BGM
@export var default_bgm_fade_time: float = 2.0
## Reference to BGM Player
@onready var bgm = %BGM
## Reference to built in Animation Player
@onready var animation_player = $DVN/AnimationPlayer
## The volume of the BGM set in the editor, used
@onready var bgm_initial_volume = bgm.get_volume_db()
## The currently active text balloon, created from [method create_text_balloon]
var current_balloon = null
#region Text Functions
## Create a text balloon starting from [param title]
func create_text_balloon(title:String):
current_balloon = Balloon.instantiate()
add_child(current_balloon)
current_balloon.start(Dialogue,title)
## Wait a certain amount of [param time] until the next dialogue line is executed
func delay(time:float = 2.0):
await get_tree().create_timer(time).timeout
emit_signal("delay_ended")
screen_fade_out.connect(on_delay_ended)
## Switch the currently selected [DVNLabel]
## [br]If [param keep_text] is true than the previously selected [DVNLabel] will stay drawn
func switch_label(label,keep_text: bool = false):
if keep_text == false:
current_balloon.dialogue_label.text = ""
current_balloon.dialogue_label = label
## Move the selected [param label] to a specified [param position]
func move_label(label:PackedScene,position:Vector2):
current_balloon.dialogue_label.position = position
## Change the [param color] of the currently selected label
func change_text_color(color:Color):
current_balloon.dialogue_label.set_modulate(color)
## Set the current dialogue automation type.
## [br]see [enum DialogueAutomationTypes] for more info
func set_dialogue_automation_type(type:int):
dialogue_automation_type = type
## Set the text speed in seconds per step
func set_text_speed(speed:float=0.02):
current_balloon.dialogue_label.seconds_per_step = speed
## Called when the dialogue reaches an END block.
func dialogue_ended():
pass
#endregion
#region Voice Functions
## Set the current voice line position. Useful if you have a lot of different branches
## and loops in dialogue.
func set_voice_line(index:int):
current_balloon.dialogue_label.current_voice_line = index
## Set if speech sounds should play at all.
func set_can_speak(truefalse:bool=true):
current_balloon.dialogue_label.can_speak = truefalse
## Set the volume of the currently selected [DVNLabel]'s talktone player in db
func set_voice_volume(volume:float = 0.0):
current_balloon.dialogue_label.talktone_player.set_volume_db(volume)
#endregion
#region Screen Fade Functions
## Fades in the screen. This is achieved by interpolating the alpha of [DVNScene]'s [ColorRect].
## [br][br][param color] determines the color to fade in from.
## [br][param time] determines the amount of time for the fade to take.
## [br][param hold_time] determines the time to wait until the screen starts fading.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_in_screen(color:Color = Color.BLACK,time:float = default_screen_fade_time,hold_time:float = 0,async:bool = false):
%FadeColor.color = color
%FadeColor.color.a = 1.0
await get_tree().create_timer(hold_time).timeout
var tween = get_tree().create_tween()
tween.tween_property(%FadeColor, "color:a", 0.0, time).set_trans(Tween.TRANS_LINEAR)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("screen_fade_in")
screen_fade_out.connect(on_screen_fade_in)
## Fades out the screen. This is achieved by interpolating the alpha of [DVNScene]'s [ColorRect].
## [br][br][param color] determines the color to fade to.
## [br][param time] determines the amount of time for the fade to take.
## [br][param hold_time] determines the extra time to hold the faded color, until the fading is considered "finished".
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_out_screen(color:Color = Color.BLACK,time:float = default_screen_fade_time,hold_time:float = 0,async:bool = false):
%FadeColor.color = color
%FadeColor.color.a = 0.0
var tween = get_tree().create_tween()
tween.tween_property(%FadeColor, "color:a", 1.0, time).set_trans(Tween.TRANS_LINEAR)
if !async:
await get_tree().create_timer(time).timeout
await get_tree().create_timer(hold_time).timeout
emit_signal("screen_fade_in")
screen_fade_out.connect(on_screen_fade_in)
#endregion
#region BGM Fade Functions
## Fades out BGM. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_out_bgm(time:float = default_bgm_fade_time,async:bool = false):
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", -80, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade_out")
bgm_fade_in.connect(on_bgm_fade_in)
## Fades in BGM. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_in_bgm(time:float = default_bgm_fade_time,async:bool = false):
bgm.set_volume_db(-80)
bgm.play()
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", bgm_initial_volume, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade_in")
bgm_fade_in.connect(on_bgm_fade_in)
## Fades the BGM from its current value to [param end_volume]. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_bgm(end_volume:float = 0.0,time:float = default_bgm_fade_time,async:bool = false):
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", end_volume, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade")
bgm_fade.connect(on_bgm_fade)
## Change BGM to [param stream]
func change_bgm(stream:AudioStream):
bgm.stream = stream
## Pause/Resume BGM
func pause_bgm(pause:bool = true):
bgm.set_stream_paused(pause)
## STOP BGM.
func stop_bgm():
bgm.stop()
## Play the BGM.
##[br]Different from setting [method pause_bgm] to false as this will start the stream from the beginning
func play_bgm():
bgm.play()
## Set the BGM Volume in db.
## [br]Does not fade, volume change is abrupt.
func set_bgm_volume(volume:float = 0.0):
bgm.set_volume_db(volume)
## Skip to a spot in the BGM. see [method AudioStreamPlayer.seek]
func seek_bgm(to_position:float = 0.0):
bgm.seek(to_position)
#endregion
#region SFX Functions
## Play a sound effect. Achieved by creating an [AudioStreamPlayer] and freeing it when it's done playing.
## [br][br]The specific [param sound] can be changed, along with its [param volume] and [param pitch].
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
## [br][br]The Sound effect will play from the SFX audio bus.
func play_sound(sound:AudioStream,volume:float,pitch:float,async:bool = true):
var sfx = load("res://dvn/sound_player/sound.tscn").instantiate()
sfx.stream = sound
sfx.set_volume_db(volume)
sfx.pitch_scale = pitch
add_child(sfx)
sfx.play()
if !async:
await get_tree().create_timer(sound.get_length()).timeout
emit_signal("sound_ended")
sound_ended.connect(on_sound_ended)
#endregion
#region Animation Functions
## Sets an [AnimationPlayer]'s [param speed].
## [br] by default this affects the [DVNScene]'s built in [AnimationPlayer]
## [br][br] see [method AnimationPlayer.set_speed_scale]
func set_animation_speed(speed:float = 1.0,player:Node = animation_player):
animation_player.set_speed_scale(1.0)
## Play an anim on your [AnimationPlayer].
## [br] by default this affects the [DVNScene]'s built in [AnimationPlayer]
## [br][br] see [method AnimationPlayer.play]
func play_animtion(animation:String,player = animation_player):
player.play(animation)
#endregion
#region Scene Functions
## Go to the next [param scene] from a node's path. [param example: "res://dvn/dvn.tscn"]
## [br]can be used to change the current scene to anything, but you generally want
## to use it to move to the next specific "scene" or "level"
func change_scene(scene:String):
get_tree().change_scene_to_file(scene)
## Ends the scene with a screen and BGM fade out. When the screen and BGM are done fading, the scene switches to [param next_scene]
## [br][param screen_fade_time] and [param bgm_fade_time] can be adjusted, though by default they are set to [member default_screen_fade_time] and [member default_bgm_fade_time]
## [br]You can set the default fade times in [DVNScene]'s exports.
## [br]Ideally this is the kind of function you can use to smoothly end a scene in one line.
func end_scene(next_scene:String,screen_fade_time:float = default_screen_fade_time,bgm_fade_time:float = default_bgm_fade_time):
#Determine whether to end on bgm fade or screen fade
var wait_time = 0.0
if bgm_fade_time > screen_fade_time:
wait_time = bgm_fade_time
else:
wait_time = screen_fade_time
#fade bgm and screen
fade_out_bgm(bgm_fade_time)
fade_out_screen(%FadeColor.color,screen_fade_time)
await get_tree().create_timer(wait_time).timeout #wait for bgm and screen to finish fading
change_scene(next_scene)
#endregion
#region Signals
## Called when [method delay] has counted all the way down.
func on_delay_ended():
pass
## Called when [method fade_out_sceen] has finished fading the screen and [param hold_time] has counted all the way down.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_screen_fade_out():
pass
## Called when [method fade_in_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_screen_fade_in():
pass
## Called when the sound created by [method play_sound] has finished playing.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_sound_ended():
pass
## Called when [method fade_out_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade_out():
pass
## Called when [method fade_in_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade_in():
pass
## Called when [method fade_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade():
pass
## Called when... when... when something happens. make good use of that [param anim_name]!!!
func _on_animation_player_animation_finished(anim_name: StringName) -> void:
pass # Replace with function body.
#endregion

BIN
addons/dvn/dvn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

34
addons/dvn/dvn.png.import Normal file
View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://be46s5lqu5hyb"
path="res://.godot/imported/dvn.png-739544208bd6b78f8b675b31cbd71369.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/dvn/dvn.png"
dest_files=["res://.godot/imported/dvn.png-739544208bd6b78f8b675b31cbd71369.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

25
addons/dvn/dvn.tscn Normal file
View file

@ -0,0 +1,25 @@
[gd_scene load_steps=3 format=3 uid="uid://bd7pbhempcian"]
[ext_resource type="Script" path="res://addons/dvn/dvn.gd" id="1_0ao5y"]
[ext_resource type="AudioStream" uid="uid://7fnndwc2fe7i" path="res://dvn/test_resources/sound_test.wav" id="2_pjx2r"]
[node name="Scene" type="Node2D"]
script = ExtResource("1_0ao5y")
[node name="DVN" type="Node" parent="."]
[node name="FadeColor" type="ColorRect" parent="DVN"]
unique_name_in_owner = true
offset_right = 1920.0
offset_bottom = 1080.0
color = Color(0, 0, 0, 0)
[node name="BGM" type="AudioStreamPlayer" parent="DVN"]
unique_name_in_owner = true
stream = ExtResource("2_pjx2r")
bus = &"BGM"
[node name="AnimationPlayer" type="AnimationPlayer" parent="DVN"]
root_node = NodePath("../..")
[connection signal="animation_finished" from="DVN/AnimationPlayer" to="." method="_on_animation_player_animation_finished"]

2
addons/dvn/dvn_plugin.gd Normal file
View file

@ -0,0 +1,2 @@
@tool
extends EditorPlugin

View file

@ -0,0 +1,134 @@
@icon("res://addons/dialogue_manager/assets/icon.svg")
class_name DVNLabel extends DialogueLabel
## The DVNLabel Class takes care of dialogue related functions on the label-level
## ToneTypes for the Talktone player.
## [br][param NONE] plays no sound when text is outputted
## [br][param VOICE] plays a [AudioStream] from [member voice_clips] at the beginning of each dialogue box,
## the index of [member voice clips] increases with each dialogue box. Use this for full voice acting.
## [br][param HALF_BEEP] plays a [member beep_noise] for every other letter outputted
## [br][param BEEP] plays a [member beep_noise] for every letter outputted
## [br][param BLABBER] plays a random [AudioStream] from [member blabber_noises] for every letter outputted.
## Its pitch is a random value between [member blabber_pitch_minumum] and [member blabber_pitch_maximum]
## [br][param MARISESE] uses rudimentary voice synthesis (a specific sound is mapped to each letter aka each [AudioStream] from values 0-25, with every other symbol being represented by value 26)
## ## Its pitch is a random value between [member marisese_pitch_minumum] and [member marisese_pitch_maximum]
enum ToneTypes{NONE,VOICE,HALF_BEEP,BEEP,BLABBER,MARISESE}
@export var talktone_player_path: NodePath
var talktone_player = null
var current_voice_line:int = 0
# Current TalkType
@export_enum("None","Voice","Half Beep","Beep","Blabber","Marisese") var tone_type: int
# Tone Noises
@export var voice_clips: Array[Resource] = []
@export var beep_noise: Resource
@export var blabber_noises: Array[Resource] = []
@export var blabber_pitch_minumum: float = 1.0
@export var blabber_pitch_maximum: float = 1.0
@export var marisese_noises: Array[Resource] = []
@export var marisese_pitch_minumum: float = 0.9
@export var marisese_pitch_maximum: float = 1.1
@export var can_speak: bool = true
@onready var scene = get_owner().get_parent()
@onready var balloon = get_owner()
func _init() -> void:
bbcode_enabled = true
fit_content = true
scroll_active = false
shortcut_keys_enabled = false
meta_underlined = false
hint_underlined = false
deselect_on_focus_loss_enabled = false
visible_characters_behavior = TextServer.VisibleCharactersBehavior.VC_CHARS_AFTER_SHAPING
set_anchors_preset(Control.PRESET_TOP_WIDE)
size.x = 640.0
mouse_filter = MOUSE_FILTER_PASS
func _ready() -> void:
talktone_player = get_node(talktone_player_path)
talktone_player.finished.connect(on_talktone_finished)
spoke.connect(_on_spoke)
finished_typing.connect(_on_finished_typing)
func type_out():
super()
if tone_type == ToneTypes.VOICE && can_speak:
if current_voice_line <= voice_clips.size() - 1:
talktone_player.stream = voice_clips[current_voice_line]
talktone_player.play()
current_voice_line += 1
func play_beep_tone(sound:Resource = beep_noise,pitch_minimum:float = 1.0,pitch_maximum:float = 1.0,player:Node = talktone_player):
var r = randf_range(pitch_minimum,pitch_maximum)
player.stream = sound
player.pitch_scale = r
player.play()
func play_blabber_tone(sounds:Array = blabber_noises,volume:float = 0.0,pitch_minimum:float = blabber_pitch_minumum,pitch_maximum:float = blabber_pitch_maximum,player:Node = talktone_player):
var r = randi_range(0,sounds.size() - 1)
player.stream = sounds[r]
var r2 = randf_range(pitch_minimum,pitch_maximum)
player.pitch_scale = r2
player.play()
func play_marisese(letter:String = "A",sounds:Array = marisese_noises,volume:float = 0.0,pitch_minimum:float = marisese_pitch_minumum,pitch_maximum:float = marisese_pitch_maximum,player:Node = talktone_player):
var snd = 26
#region check every letter
match letter.to_upper():
"A": snd = 0
"B": snd = 1
"C": snd = 2
"D": snd = 3
"E": snd = 4
"F": snd = 5
"G": snd = 6
"H": snd = 7
"I": snd = 8
"J": snd = 9
"K": snd = 10
"L": snd = 11
"M": snd = 12
"N": snd = 13
"O": snd = 14
"P": snd = 15
"Q": snd = 16
"R": snd = 17
"S": snd = 18
"T": snd = 19
"U": snd = 20
"V": snd = 21
"W": snd = 22
"X": snd = 23
"Y": snd = 24
"Z": snd = 25
#endregion
player.stream = sounds[snd]
var r = randf_range(pitch_minimum,pitch_maximum)
player.pitch_scale = r
player.play()
func _on_spoke(letter: String, letter_index: int, speed: float) -> void:
if can_speak:
match tone_type:
ToneTypes.HALF_BEEP:
if letter_index % 2 == 0:
play_beep_tone()
ToneTypes.BEEP:
play_beep_tone()
ToneTypes.BLABBER:
play_blabber_tone()
ToneTypes.MARISESE:
play_marisese(letter)
func on_talktone_finished():
if scene.dialogue_automation_type == scene.DialogueAutomationTypes.AUTO_VOICE:
balloon.next(balloon.dialogue_line.next_id)
func _on_finished_typing():
if scene.dialogue_automation_type == scene.DialogueAutomationTypes.AUTO_TEXT:
await get_tree().create_timer(scene.auto_text_delay).timeout
if balloon.dialogue_line.responses.size() == 0:
balloon.next(balloon.dialogue_line.next_id)

View file

@ -0,0 +1,82 @@
[gd_scene load_steps=71 format=3 uid="uid://cca3fm3pojb41"]
[ext_resource type="Script" path="res://addons/dvn/label/dvn_label.gd" id="1_fv617"]
[ext_resource type="AudioStream" uid="uid://b5g1o68bedpma" path="res://dvn/test_resources/punchy_2.ogg" id="2_hquny"]
[ext_resource type="AudioStream" uid="uid://sm4230h82f5q" path="res://dvn/test_resources/blabber/pi1.wav" id="2_tuq54"]
[ext_resource type="AudioStream" uid="uid://b5kfcwr6q6dps" path="res://dvn/test_resources/blabber/fal1.wav" id="3_bmk75"]
[ext_resource type="AudioStream" uid="uid://bg3bavm00pcnk" path="res://dvn/test_resources/blabber/pe1.wav" id="3_d0ft6"]
[ext_resource type="AudioStream" uid="uid://bpgaqfi7u7lxs" path="res://dvn/test_resources/blabber/far1.wav" id="4_1qnca"]
[ext_resource type="AudioStream" uid="uid://t3re1rycy7j2" path="res://dvn/test_resources/blabber/ga1.wav" id="5_cbw33"]
[ext_resource type="AudioStream" uid="uid://0v1iv2ra8x8w" path="res://dvn/test_resources/blabber/ga2.wav" id="6_40gsr"]
[ext_resource type="AudioStream" uid="uid://b2wynph473uvs" path="res://dvn/test_resources/blabber/le1.wav" id="7_ibxmc"]
[ext_resource type="AudioStream" uid="uid://dqltsvqf3k6vc" path="res://dvn/test_resources/blabber/ne1'.wav" id="8_jtpjw"]
[ext_resource type="AudioStream" uid="uid://dfv7i773v1345" path="res://dvn/test_resources/blabber/ni.wav" id="9_54x41"]
[ext_resource type="AudioStream" uid="uid://dxfs35l47g73l" path="res://dvn/test_resources/blabber/pa1.wav" id="10_u3rmo"]
[ext_resource type="AudioStream" uid="uid://chppepwyeaxo1" path="res://dvn/test_resources/blabber/ri1.wav" id="13_qjq1i"]
[ext_resource type="AudioStream" uid="uid://dalsdbfgokvh8" path="res://dvn/test_resources/blabber/ri2.wav" id="14_ubu0w"]
[ext_resource type="AudioStream" uid="uid://mwypw3x0tsjd" path="res://dvn/test_resources/blabber/sd1.wav" id="15_8x2tu"]
[ext_resource type="AudioStream" uid="uid://g64h12p8xumh" path="res://dvn/test_resources/blabber/sd2.wav" id="16_doa2h"]
[ext_resource type="AudioStream" uid="uid://do4bmxgaj20n" path="res://dvn/test_resources/blabber/sd3.wav" id="17_l6dov"]
[ext_resource type="AudioStream" uid="uid://5fmqnqdna8lv" path="res://dvn/test_resources/blabber/sd4.wav" id="18_pdvjt"]
[ext_resource type="AudioStream" uid="uid://bxjkrlc4vt2kh" path="res://dvn/test_resources/blabber/sd5.wav" id="19_4s5lc"]
[ext_resource type="AudioStream" uid="uid://b0ys7cac48mox" path="res://dvn/test_resources/blabber/sd6.wav" id="20_m42sg"]
[ext_resource type="AudioStream" uid="uid://i77kull066ki" path="res://dvn/test_resources/blabber/sd7.wav" id="21_hcdah"]
[ext_resource type="AudioStream" uid="uid://cx76n171p3cuj" path="res://dvn/test_resources/blabber/sd8.wav" id="22_cexo3"]
[ext_resource type="AudioStream" uid="uid://cq2ogvp0ojpfn" path="res://dvn/test_resources/blabber/sd9.wav" id="23_v8lqv"]
[ext_resource type="AudioStream" uid="uid://cnre5w258b5h8" path="res://dvn/test_resources/blabber/sd10.wav" id="24_o3iql"]
[ext_resource type="AudioStream" uid="uid://0hucylbigf3v" path="res://dvn/test_resources/blabber/sd11.wav" id="25_577es"]
[ext_resource type="AudioStream" uid="uid://61m5vy2qnxog" path="res://dvn/test_resources/blabber/sd12.wav" id="26_yuaul"]
[ext_resource type="AudioStream" uid="uid://cirx6t05t8ao0" path="res://dvn/test_resources/blabber/sd13.wav" id="27_nlfp5"]
[ext_resource type="AudioStream" uid="uid://c36rbn6sic5pt" path="res://dvn/test_resources/blabber/sd14.wav" id="28_3ag1d"]
[ext_resource type="AudioStream" uid="uid://bpa2mw442i3xc" path="res://dvn/test_resources/blabber/sd15.wav" id="29_ph7ej"]
[ext_resource type="AudioStream" uid="uid://cjl1n6g2m36b" path="res://dvn/test_resources/blabber/sd16.wav" id="30_envgi"]
[ext_resource type="AudioStream" uid="uid://ge3im18rj7ay" path="res://dvn/test_resources/blabber/sd17.wav" id="31_6w17e"]
[ext_resource type="AudioStream" uid="uid://bhyypbcfh348o" path="res://dvn/test_resources/blabber/sd18.wav" id="32_ms2qy"]
[ext_resource type="AudioStream" uid="uid://gwk6piygd8ui" path="res://dvn/test_resources/blabber/sd19.wav" id="33_u3qhm"]
[ext_resource type="AudioStream" uid="uid://ceq1ke4reramj" path="res://dvn/test_resources/blabber/sd20.wav" id="34_r1oa5"]
[ext_resource type="AudioStream" uid="uid://8wjlqeg6b8xx" path="res://dvn/test_resources/blabber/sd21.wav" id="35_mqmkp"]
[ext_resource type="AudioStream" uid="uid://bqfn6evn120or" path="res://dvn/test_resources/blabber/sd22.wav" id="36_nlt07"]
[ext_resource type="AudioStream" uid="uid://i7lo7bm16vff" path="res://dvn/test_resources/blabber/sd23.wav" id="37_mstcy"]
[ext_resource type="AudioStream" uid="uid://bax606i3nxh7l" path="res://dvn/test_resources/blabber/ss1.wav" id="38_0v0fh"]
[ext_resource type="AudioStream" uid="uid://37cucmolvd3f" path="res://dvn/test_resources/blabber/ta1.wav" id="39_bhuw4"]
[ext_resource type="AudioStream" uid="uid://c58ka00u052yv" path="res://dvn/test_resources/blabber/te1.wav" id="40_i10fu"]
[ext_resource type="AudioStream" uid="uid://dcqmpdxusohbq" path="res://dvn/test_resources/blabber/ti1.wav" id="41_ijnny"]
[ext_resource type="AudioStream" uid="uid://dtdt4e3u6nvnv" path="res://dvn/test_resources/blabber/to1.wav" id="42_b88mp"]
[ext_resource type="AudioStream" uid="uid://i5d6kk1knsma" path="res://dvn/test_resources/blabber/za1.wav" id="43_2ojxd"]
[ext_resource type="AudioStream" uid="uid://lj6cmjs2fcoy" path="res://dvn/test_resources/marisese/a.ogg" id="44_0vfbl"]
[ext_resource type="AudioStream" uid="uid://hpua870udnef" path="res://dvn/test_resources/marisese/b.ogg" id="45_61hs3"]
[ext_resource type="AudioStream" uid="uid://cjvp4618k1655" path="res://dvn/test_resources/marisese/c.ogg" id="46_liuih"]
[ext_resource type="AudioStream" uid="uid://mdubpok7ngrq" path="res://dvn/test_resources/marisese/d.ogg" id="47_r6a1e"]
[ext_resource type="AudioStream" uid="uid://b4au507qswa1v" path="res://dvn/test_resources/marisese/e.ogg" id="48_llf7d"]
[ext_resource type="AudioStream" uid="uid://d1osi4yd264ha" path="res://dvn/test_resources/marisese/f.ogg" id="49_lu43n"]
[ext_resource type="AudioStream" uid="uid://d2tf84enhxeb7" path="res://dvn/test_resources/marisese/g.ogg" id="50_x05xc"]
[ext_resource type="AudioStream" uid="uid://b8bbdmrbv4enj" path="res://dvn/test_resources/marisese/h.ogg" id="51_l7627"]
[ext_resource type="AudioStream" uid="uid://d3ckkydmnk8gl" path="res://dvn/test_resources/marisese/i.ogg" id="52_ho0bb"]
[ext_resource type="AudioStream" uid="uid://cimlinpp0blqe" path="res://dvn/test_resources/marisese/j.ogg" id="53_4wpxl"]
[ext_resource type="AudioStream" uid="uid://od5mo70vksk" path="res://dvn/test_resources/marisese/k.ogg" id="54_i0f61"]
[ext_resource type="AudioStream" uid="uid://cms646gy24tg1" path="res://dvn/test_resources/marisese/l.ogg" id="55_fjfa5"]
[ext_resource type="AudioStream" uid="uid://drcrhooamcuv4" path="res://dvn/test_resources/marisese/m.ogg" id="56_u00wn"]
[ext_resource type="AudioStream" uid="uid://bqoygbln7xe5b" path="res://dvn/test_resources/marisese/n.ogg" id="57_d5p6b"]
[ext_resource type="AudioStream" uid="uid://nrhmwe1yb04k" path="res://dvn/test_resources/marisese/o.ogg" id="58_uk4g0"]
[ext_resource type="AudioStream" uid="uid://hycxcbqq6i6d" path="res://dvn/test_resources/marisese/p.ogg" id="59_nntae"]
[ext_resource type="AudioStream" uid="uid://fkdc5nuwwtrv" path="res://dvn/test_resources/marisese/q.ogg" id="60_3nwmx"]
[ext_resource type="AudioStream" uid="uid://cnw5pe2mew1ns" path="res://dvn/test_resources/marisese/r.ogg" id="61_81l4p"]
[ext_resource type="AudioStream" uid="uid://dr52n8ld32c3h" path="res://dvn/test_resources/marisese/s.ogg" id="62_mb7y7"]
[ext_resource type="AudioStream" uid="uid://loxlrrvh88gx" path="res://dvn/test_resources/marisese/t.ogg" id="63_0rkin"]
[ext_resource type="AudioStream" uid="uid://borglhy7pdu7a" path="res://dvn/test_resources/marisese/u.ogg" id="64_81htt"]
[ext_resource type="AudioStream" uid="uid://cwgc5q6gkk24m" path="res://dvn/test_resources/marisese/v.ogg" id="65_j0h54"]
[ext_resource type="AudioStream" uid="uid://d3d4qd504q88s" path="res://dvn/test_resources/marisese/w.ogg" id="66_qvihc"]
[ext_resource type="AudioStream" uid="uid://2yfoybsar237" path="res://dvn/test_resources/marisese/x.ogg" id="67_5y7v3"]
[ext_resource type="AudioStream" uid="uid://bl6crwxrpbtn1" path="res://dvn/test_resources/marisese/y.ogg" id="68_k2fgx"]
[ext_resource type="AudioStream" uid="uid://24xlk8xji84c" path="res://dvn/test_resources/marisese/z.ogg" id="69_gfbuo"]
[ext_resource type="AudioStream" uid="uid://dov7x4duhpcmv" path="res://dvn/test_resources/marisese/null.ogg" id="70_cva4i"]
[node name="DVNLabel" type="RichTextLabel"]
script = ExtResource("1_fv617")
talktone_player_path = NodePath("../../../../../AudioStreamPlayer")
tone_type = 3
beep_noise = ExtResource("2_hquny")
blabber_noises = Array[Resource]([ExtResource("3_bmk75"), ExtResource("4_1qnca"), ExtResource("5_cbw33"), ExtResource("6_40gsr"), ExtResource("7_ibxmc"), ExtResource("8_jtpjw"), ExtResource("9_54x41"), ExtResource("10_u3rmo"), ExtResource("3_d0ft6"), ExtResource("2_tuq54"), ExtResource("13_qjq1i"), ExtResource("14_ubu0w"), ExtResource("15_8x2tu"), ExtResource("16_doa2h"), ExtResource("17_l6dov"), ExtResource("18_pdvjt"), ExtResource("19_4s5lc"), ExtResource("20_m42sg"), ExtResource("21_hcdah"), ExtResource("22_cexo3"), ExtResource("23_v8lqv"), ExtResource("24_o3iql"), ExtResource("25_577es"), ExtResource("26_yuaul"), ExtResource("27_nlfp5"), ExtResource("28_3ag1d"), ExtResource("29_ph7ej"), ExtResource("30_envgi"), ExtResource("31_6w17e"), ExtResource("32_ms2qy"), ExtResource("33_u3qhm"), ExtResource("34_r1oa5"), ExtResource("35_mqmkp"), ExtResource("36_nlt07"), ExtResource("37_mstcy"), ExtResource("38_0v0fh"), ExtResource("39_bhuw4"), ExtResource("40_i10fu"), ExtResource("41_ijnny"), ExtResource("42_b88mp"), ExtResource("43_2ojxd")])
marisese_noises = Array[Resource]([ExtResource("44_0vfbl"), ExtResource("45_61hs3"), ExtResource("46_liuih"), ExtResource("47_r6a1e"), ExtResource("48_llf7d"), ExtResource("49_lu43n"), ExtResource("50_x05xc"), ExtResource("51_l7627"), ExtResource("52_ho0bb"), ExtResource("53_4wpxl"), ExtResource("54_i0f61"), ExtResource("55_fjfa5"), ExtResource("56_u00wn"), ExtResource("57_d5p6b"), ExtResource("58_uk4g0"), ExtResource("59_nntae"), ExtResource("60_3nwmx"), ExtResource("61_81l4p"), ExtResource("62_mb7y7"), ExtResource("63_0rkin"), ExtResource("64_81htt"), ExtResource("65_j0h54"), ExtResource("66_qvihc"), ExtResource("67_5y7v3"), ExtResource("68_k2fgx"), ExtResource("69_gfbuo"), ExtResource("70_cva4i")])
[connection signal="spoke" from="." to="." method="_on_spoke"]

7
addons/dvn/plugin.cfg Normal file
View file

@ -0,0 +1,7 @@
[plugin]
name="DVN"
description="Expansion of Nathan Hoad's \"Dialogue Manager\" addon."
author="PennyRigate"
version="1.0"
script="dvn_plugin.gd"

View file

@ -0,0 +1,4 @@
extends AudioStreamPlayer
func _on_finished() -> void:
queue_free()

View file

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://bldqqpajcj62n"]
[ext_resource type="Script" path="res://addons/dvn/sound_player/sound.gd" id="1_boi0g"]
[node name="Sound" type="AudioStreamPlayer"]
bus = &"SFX"
script = ExtResource("1_boi0g")
[connection signal="finished" from="." to="." method="_on_finished"]

1
icon.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>

After

Width:  |  Height:  |  Size: 994 B

37
icon.svg.import Normal file
View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://g6mbh8mhg11n"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

46
project.godot Normal file
View file

@ -0,0 +1,46 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="dvn"
run/main_scene="res://dvn/test_resources/test_system.tscn"
config/features=PackedStringArray("4.3", "GL Compatibility")
config/icon="res://icon.svg"
[audio]
buses/default_bus_layout="res://addons/dvn/default_bus_layout.tres"
[autoload]
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
[dialogue_manager]
runtime/balloon_path="res:///balloon.tscn"
[display]
window/size/viewport_width=640
window/size/viewport_height=480
[editor_plugins]
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg", "res://addons/dvn/plugin.cfg")
[internationalization]
locale/translations_pot_files=PackedStringArray("res://addons/dvn/test_resources/test_dialgoue.dialogue")
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"