diff --git a/backend/scripts/game.gd b/backend/scripts/game.gd index 9db3a1e..a51273e 100644 --- a/backend/scripts/game.gd +++ b/backend/scripts/game.gd @@ -1,8 +1,55 @@ extends Node class_name Game -@export var dialogue_scene: DialogueScene +static var currentSave : String +@export var current_scene: DialogueScene + +## check if event in events list +static func has_event_data(event: String) -> bool: + # change to this when save system set up + # var eventFile : FileAccess = FileAccess.open("user://Saves/"+currentSave+"/events.txt", FileAccess.READ) + # for testing: + var eventFile : FileAccess = FileAccess.open("res://test_data/events.txt", FileAccess.READ) + while (!eventFile.eof_reached()): + var content :String = eventFile.get_line().strip_edges() + if content == event: + eventFile.close() + return true + eventFile.close() + return false + +## check if all events in events list +static func has_all_events_data(events: Array[String]) -> bool: + if events.is_empty(): + return true; + # change to this when save system set up + # var eventFile : FileAccess = FileAccess.open("user://Saves/"+currentSave+"/events.txt", FileAccess.READ) + # for testing: + var eventFile : FileAccess = FileAccess.open("res://test_data/events.txt", FileAccess.READ) + var events2 = events + while (!eventFile.eof_reached()): + var content :String = eventFile.get_line().strip_edges() + if events2.has(content): + events2.erase(content) + if events2.is_empty(): + eventFile.close() + return true + eventFile.close() + return false + + +static func log_event_data(event: String) -> void: + ## change to this when save system set up + # var eventFile : FileAccess = FileAccess.open("user://Saves/"+currentSave+"/events.txt", FileAccess.READ) + ## for testing: + var eventFile : FileAccess = FileAccess.open("res://test_data/events.txt", FileAccess.READ_WRITE) + eventFile.seek_end() + eventFile.store_line(event) + eventFile.close() + + + + func _ready() -> void: add_child(await DialogueEncounter.new(self.dialogue_scene)) - diff --git a/characters/test_character1.tres b/characters/test_character1.tres new file mode 100644 index 0000000..d7f9fad --- /dev/null +++ b/characters/test_character1.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="Character" format=3 uid="uid://c1pqvty4jtg6r"] + +[ext_resource type="Script" uid="uid://xbl6wraf2l3k" path="res://characters/character.gd" id="1_7ph4k"] + +[resource] +script = ExtResource("1_7ph4k") +character_name = "test2" +metadata/_custom_type_script = "uid://xbl6wraf2l3k" diff --git a/characters/test_character2.tres b/characters/test_character2.tres new file mode 100644 index 0000000..4b0942b --- /dev/null +++ b/characters/test_character2.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="Character" format=3 uid="uid://bp1nuugvgxstm"] + +[ext_resource type="Script" uid="uid://xbl6wraf2l3k" path="res://characters/character.gd" id="1_1e8fb"] + +[resource] +script = ExtResource("1_1e8fb") +character_name = "test1" +metadata/_custom_type_script = "uid://xbl6wraf2l3k" diff --git a/dialogue/resources/test_scene.tres b/dialogue/resources/test_scene.tres index 4b6041d..26b235c 100644 --- a/dialogue/resources/test_scene.tres +++ b/dialogue/resources/test_scene.tres @@ -3,20 +3,34 @@ [ext_resource type="Script" uid="uid://dw5jr50hsls5n" path="res://dialogue/scripts/dialogue.gd" id="1_tbx8t"] [ext_resource type="Script" uid="uid://d2d5w1vmd71js" path="res://dialogue/scripts/choice.gd" id="2_7gud4"] [ext_resource type="Script" uid="uid://cu54e7uh65lq0" path="res://dialogue/scripts/scene.gd" id="3_2c6wc"] +[ext_resource type="Script" uid="uid://bcx25iulofjjw" path="res://dialogue/scripts/choice_target.gd" id="3_7gud4"] + +[sub_resource type="Resource" id="Resource_w5su3"] +script = ExtResource("3_7gud4") +metadata/_custom_type_script = "uid://bcx25iulofjjw" + +[sub_resource type="Resource" id="Resource_6lvw1"] +script = ExtResource("2_7gud4") +response = "test1" +targets = Array[ExtResource("3_7gud4")]([SubResource("Resource_w5su3")]) +metadata/_custom_type_script = "uid://d2d5w1vmd71js" + +[sub_resource type="Resource" id="Resource_k33ik"] +script = ExtResource("2_7gud4") +response = "test2" +metadata/_custom_type_script = "uid://d2d5w1vmd71js" [sub_resource type="Resource" id="Resource_qdk4l"] script = ExtResource("1_tbx8t") -dialogue = "this is a test of the dialoge sysytem" +choices = Array[ExtResource("2_7gud4")]([SubResource("Resource_6lvw1"), SubResource("Resource_k33ik")]) metadata/_custom_type_script = "uid://dw5jr50hsls5n" [sub_resource type="Resource" id="Resource_psx0q"] script = ExtResource("1_tbx8t") -dialogue = "this should be the second message" metadata/_custom_type_script = "uid://dw5jr50hsls5n" [sub_resource type="Resource" id="Resource_elg5j"] script = ExtResource("1_tbx8t") -dialogue = "i hope you enjoyed" metadata/_custom_type_script = "uid://dw5jr50hsls5n" [resource] diff --git a/dialogue/resources/test_scene1.json b/dialogue/resources/test_scene1.json new file mode 100644 index 0000000..bb21eb0 --- /dev/null +++ b/dialogue/resources/test_scene1.json @@ -0,0 +1,40 @@ +{ + "d":[ + { + "chr": "test_character1", + "d": "Hi, I'm test1!\nNice to meet you, what's your name?", + "chs": [] + }, + { + "chr": "test_character2", + "d": "I'm test2!", + "chs": [] + }, + { + "chr": "test_character1", + "d": "Where are you from?", + "chs": [ + { + "r": "Atlanta", + "t": [ + { + "t": "test_scene3.json", + "c": [], + "e": "ATL1" + } + ] + }, + { + "r": "San Francisco", + "t": [ + { + "t": "test_scene4.json", + "c": [], + "e": "SFO1" + } + ] + } + ] + } + ] +} diff --git a/dialogue/resources/test_scene2.json b/dialogue/resources/test_scene2.json new file mode 100644 index 0000000..6bbe8c4 --- /dev/null +++ b/dialogue/resources/test_scene2.json @@ -0,0 +1,9 @@ +{ + "d":[ + { + "chr": "test_character1", + "d": "Goodbye!", + "chs": [] + } + ] +} diff --git a/dialogue/resources/test_scene3.json b/dialogue/resources/test_scene3.json new file mode 100644 index 0000000..af28d63 --- /dev/null +++ b/dialogue/resources/test_scene3.json @@ -0,0 +1,20 @@ +{ + "d":[ + { + "chr": "test_character1", + "d": "You are from Atlanta!", + "chs": [ + { + "r": "", + "t": [ + { + "t": "test_scene2.json", + "c": [], + "e": "" + } + ] + } + ] + } + ] +} diff --git a/dialogue/resources/test_scene4.json b/dialogue/resources/test_scene4.json new file mode 100644 index 0000000..639b74f --- /dev/null +++ b/dialogue/resources/test_scene4.json @@ -0,0 +1,20 @@ +{ + "d":[ + { + "chr": "test_character1", + "d": "You are from San Francisco!", + "chs": [ + { + "r": "", + "t": [ + { + "t": "test_scene2.json", + "c": [], + "e": "" + } + ] + } + ] + } + ] +} diff --git a/dialogue/scripts/choice.gd b/dialogue/scripts/choice.gd index 42a0800..d587a2e 100644 --- a/dialogue/scripts/choice.gd +++ b/dialogue/scripts/choice.gd @@ -2,4 +2,28 @@ extends Resource class_name Choice @export var response: String -@export var scene: DialogueScene +@export var targets: Array[ChoiceTarget] + +func get_target()->DialogueScene: + for target : ChoiceTarget in targets: + if target.condition_events.is_empty(): + if !target.target_event.is_empty(): + Game.log_event_data(target.target_event) + return target.target_scene + if Game.has_all_events_data(target.condition_events): + if !target.target_event.is_empty(): + Game.log_event_data(target.target_event) + return target.target_scene + print(error_string(ERR_INVALID_PARAMETER) + + " in Choice.get_target(), check that there is a target with an empty condition_events in targets") + return null + +func _init(str1 : String, targs : Array[ChoiceTarget]): + response = str1 + targets = targs + +static func load_dict(dict : Dictionary) -> Choice: + var ts : Array[ChoiceTarget] = [] + for tar : Dictionary in dict["t"]: + ts.append(ChoiceTarget.load_dict(tar)) + return new(dict["r"], ts) diff --git a/dialogue/scripts/choice_target.gd b/dialogue/scripts/choice_target.gd new file mode 100644 index 0000000..0832da8 --- /dev/null +++ b/dialogue/scripts/choice_target.gd @@ -0,0 +1,17 @@ +extends Resource +class_name ChoiceTarget +## Target scene to go to if condition is in game events. +@export var target_scene_loc: String +## An array of event names-- empty array means that this target is default. +@export var condition_events: Array[String] +## Name of event to log to events data. +## Can be empty string, in which case no event is logged. +@export var target_event: String + +func _init(t_sc_loc : String, conditions: Array, event : String): + target_scene_loc = t_sc_loc + condition_events.assign(conditions) + target_event = event + +static func load_dict(dict : Dictionary) -> ChoiceTarget: + return ChoiceTarget.new(dict["t"], dict["c"], dict["e"]) diff --git a/dialogue/scripts/choice_target.gd.uid b/dialogue/scripts/choice_target.gd.uid new file mode 100644 index 0000000..02589d1 --- /dev/null +++ b/dialogue/scripts/choice_target.gd.uid @@ -0,0 +1 @@ +uid://bcx25iulofjjw diff --git a/dialogue/scripts/dialogue.gd b/dialogue/scripts/dialogue.gd index 942c892..feca6e3 100644 --- a/dialogue/scripts/dialogue.gd +++ b/dialogue/scripts/dialogue.gd @@ -2,5 +2,17 @@ extends Resource class_name Dialogue @export var character: Character -@export_multiline() var dialogue: String +@export_multiline() var dialogue_str: String @export var choices: Array[Choice] + +func _init(chr : String, str1:String, choices1:Array[Choice]): + # there's probably a better way to do this but idk yet + character = load("res://characters/"+chr+".tres") + dialogue_str = str1 + choices = choices1 + +static func load_dict(dict: Dictionary) -> Dialogue: + var chs : Array[Choice] = [] + for ch : Dictionary in dict["chs"]: + chs.append(Choice.load_dict(ch)) + return new(dict["chr"], dict["d"], chs) diff --git a/dialogue/scripts/scene.gd b/dialogue/scripts/scene.gd index d9b101a..1141590 100644 --- a/dialogue/scripts/scene.gd +++ b/dialogue/scripts/scene.gd @@ -1,7 +1,25 @@ extends Resource class_name DialogueScene +static var baseLoc : String= "res://dialogue/resources/" @export var dialogue: Array[Dialogue] func get_scene() -> Array[Dialogue]: return self.dialogue + +func _init(dia : Array[Dialogue]) -> void: + dialogue = dia + +static func load_dict(dict : Dictionary) -> DialogueScene: + var dia : Array[Dialogue]= [] + for d :Dictionary in dict["d"]: + dia.append(Dialogue.load_dict(d)) + return new(dia) + +static func load_scene(loc: String) -> DialogueScene: + var f = FileAccess.open(baseLoc + loc, FileAccess.READ) + if f != null: + var ret = DialogueScene.load_dict(JSON.parse_string(f.get_as_text())) + f.close() + return ret + return null diff --git a/dialogue/scripts/spawn_dialogue.gd b/dialogue/scripts/spawn_dialogue.gd index f1396d2..f4f7012 100644 --- a/dialogue/scripts/spawn_dialogue.gd +++ b/dialogue/scripts/spawn_dialogue.gd @@ -17,12 +17,12 @@ func Start(): func walk_scene(next_scene: DialogueScene): print("walking scene") - for scene in next_scene.get_scene(): - print(scene.dialogue) - if scene.choices.size() > 0: - for choice in scene.choices: + for dia : Dialogue in next_scene.get_scene(): + print(dia.dialogue_str) + if dia.choices.size() > 0: + for choice: Choice in dia.choices: print(choice.response) if Input.is_key_pressed(KEY_1): - await walk_scene(scene.choices[0].scene) + await walk_scene(dia.choices[0].get_target()) step.emit() await step diff --git a/test_data/events.txt b/test_data/events.txt new file mode 100644 index 0000000..e69de29 diff --git a/tools/map/graph_file_node.gd b/tools/map/graph_file_node.gd new file mode 100644 index 0000000..3589ed0 --- /dev/null +++ b/tools/map/graph_file_node.gd @@ -0,0 +1,54 @@ +extends GraphNode +class_name GraphFileNode +var scene : DialogueScene = null +# static var base_loc :String = "res://dialogue/resources/" +var file_loc : String +func _init(loc : String): + file_loc = loc + title = loc + name = loc.replace("/", ";").replace(".","*") + scene = DialogueScene.load_scene(loc) + +func _ready(): + add_child(Control.new()) + set_slot(0, true, 0, Color.BLACK, false, 0, Color.BLACK) + + if scene == null: + return + var dias : Array[Dialogue] = scene.get_scene() + var i = 1 + for dia in dias: + if dia.choices.is_empty(): + continue + else: + for chc : Choice in dia.choices: + var l = Label.new() + if chc.response.is_empty() : + l.text = "(invisible choice)" + else: + l.text = chc.response + add_child(l) + set_slot(i, false, 0, Color.BLACK, true, 0, Color.from_hsv(float(i-1)*0.1, 1, 1)) + i+=1 +func map(ge : GraphEdit): + if scene != null: + var to_map_arr : Array[GraphFileNode] = [] + var dias : Array[Dialogue] = scene.get_scene() + var i = 0 + for dia in dias: + + if dia.choices.is_empty(): + continue + else: + for chc : Choice in dia.choices: + for t : ChoiceTarget in chc.targets: + var name1 = t.target_scene_loc.replace("/", ";").replace(".","*") + var outNode : GraphFileNode + if !ge.has_node(name1): + outNode = GraphFileNode.new(t.target_scene_loc) + ge.add_child(outNode) + to_map_arr.append(outNode) + ge.connect_node(self.name, i, name1, 0) + i+=1 + for to_map : GraphFileNode in to_map_arr: + to_map.map(ge) diff --git a/tools/map/graph_file_node.gd.uid b/tools/map/graph_file_node.gd.uid new file mode 100644 index 0000000..f7165c7 --- /dev/null +++ b/tools/map/graph_file_node.gd.uid @@ -0,0 +1 @@ +uid://bnyumo4kb4h1q diff --git a/tools/map/map.gd b/tools/map/map.gd new file mode 100644 index 0000000..8fd8b7b --- /dev/null +++ b/tools/map/map.gd @@ -0,0 +1,11 @@ +extends Node +func _on_map_button_button_up() -> void: + $UI/VBox/GraphEdit.clear_connections() + for child in $UI/VBox/GraphEdit.get_children(): + if child is GraphFileNode : + $UI/VBox/GraphEdit.remove_child(child) + child.queue_free() + var startNode : GraphFileNode = GraphFileNode.new("test_scene1.json") + $UI/VBox/GraphEdit.add_child(startNode) + startNode.map($UI/VBox/GraphEdit) + $UI/VBox/GraphEdit.arrange_nodes() diff --git a/tools/map/map.gd.uid b/tools/map/map.gd.uid new file mode 100644 index 0000000..ab2e1e3 --- /dev/null +++ b/tools/map/map.gd.uid @@ -0,0 +1 @@ +uid://dvomfsvrdv4pr diff --git a/tools/map/map.tscn b/tools/map/map.tscn new file mode 100644 index 0000000..ab19ce0 --- /dev/null +++ b/tools/map/map.tscn @@ -0,0 +1,33 @@ +[gd_scene format=3 uid="uid://bvgr4gp4xnqdl"] + +[ext_resource type="Script" uid="uid://dvomfsvrdv4pr" path="res://tools/map/map.gd" id="1_6lvw1"] + +[node name="Map" type="Node" unique_id=1335935698] +script = ExtResource("1_6lvw1") + +[node name="UI" type="Control" parent="." unique_id=1741993090] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBox" type="VBoxContainer" parent="UI" unique_id=2056072322] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +alignment = 1 + +[node name="MapButton" type="Button" parent="UI/VBox" unique_id=2030873199] +layout_mode = 2 +text = "Map!" + +[node name="GraphEdit" type="GraphEdit" parent="UI/VBox" unique_id=49166899] +custom_minimum_size = Vector2(100, 500) +layout_mode = 2 + +[connection signal="button_up" from="UI/VBox/MapButton" to="." method="_on_map_button_button_up"]